New TV UI (#950)

This commit is contained in:
KingLucius 2024-03-09 16:24:38 +02:00 committed by GitHub
parent bd69054f5d
commit 510d11f705
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 633 additions and 569 deletions

View file

@ -1190,7 +1190,25 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricAu
}
if(isTrueTvSettings()) {
// Put here any button you don't want focusing it to center the view
val exceptionButtons = listOf(
R.id.home_preview_play_btt,
R.id.home_preview_info_btt,
R.id.home_preview_hidden_next_focus,
R.id.home_preview_hidden_prev_focus,
R.id.result_play_movie_button,
R.id.result_play_series_button,
R.id.result_resume_series_button,
R.id.result_play_trailer_button,
R.id.result_bookmark_Button,
R.id.result_favorite_Button,
R.id.result_subscribe_Button,
R.id.result_search_Button,
R.id.result_episodes_show_button,
)
newLocalBinding.root.viewTreeObserver.addOnGlobalFocusChangeListener { _, newFocus ->
if (exceptionButtons.contains(newFocus?.id)) return@addOnGlobalFocusChangeListener
centerView(newFocus)
}
}

View file

@ -529,6 +529,7 @@ class HomeFragment : Fragment() {
super.onScrolled(recyclerView, dx, dy)
}
})
}

View file

@ -33,13 +33,13 @@ import com.lagradost.cloudstream3.ui.WatchType
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup
import com.lagradost.cloudstream3.ui.player.ExtractorLinkGenerator
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment
import com.lagradost.cloudstream3.ui.result.ResultFragment.getStoredData
import com.lagradost.cloudstream3.ui.result.ResultFragment.updateUIEvent
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_FOCUSED
import com.lagradost.cloudstream3.ui.search.SearchAdapter
import com.lagradost.cloudstream3.ui.search.SearchHelper
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
import com.lagradost.cloudstream3.utils.AppUtils.html
import com.lagradost.cloudstream3.utils.AppUtils.isRtl
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
@ -129,9 +129,9 @@ class ResultFragmentTv : Fragment() {
* Note that this will steal any focus if the episode loading is too slow (unlikely).
*/
private fun focusPlayButton() {
binding?.resultPlayMovie?.requestFocus()
binding?.resultPlaySeries?.requestFocus()
binding?.resultResumeSeries?.requestFocus()
binding?.resultPlayMovieButton?.requestFocus()
binding?.resultPlaySeriesButton?.requestFocus()
binding?.resultResumeSeriesButton?.requestFocus()
}
private fun setRecommendations(rec: List<SearchResponse>?, validApiName: String?) {
@ -246,37 +246,15 @@ class ResultFragmentTv : Fragment() {
storedData.start
)
// ===== ===== =====
var comingSoon = false
binding?.apply {
//episodesShadow.rotationX = 180.0f//if(episodesShadow.isRtl()) 180.0f else 0.0f
val leftListener: View.OnFocusChangeListener =
View.OnFocusChangeListener { _, hasFocus ->
if (!hasFocus) return@OnFocusChangeListener
toggleEpisodes(false)
}
val rightListener: View.OnFocusChangeListener =
View.OnFocusChangeListener { _, hasFocus ->
if (!hasFocus) return@OnFocusChangeListener
toggleEpisodes(true)
}
resultPlayMovie.onFocusChangeListener = leftListener
resultPlaySeries.onFocusChangeListener = leftListener
resultResumeSeries.onFocusChangeListener = leftListener
resultPlayTrailer.onFocusChangeListener = leftListener
resultEpisodesShow.onFocusChangeListener = rightListener
resultDescription.onFocusChangeListener = leftListener
resultBookmarkButton.onFocusChangeListener = leftListener
resultFavoriteButton.onFocusChangeListener = leftListener
resultEpisodesShow.setOnClickListener {
// toggle, to make it more touch accessable just in case someone thinks that a
// tv layout is better but is using a touch device
toggleEpisodes(!episodeHolderTv.isVisible)
}
// resultEpisodes.onFocusChangeListener = leftListener
// parallax on background
resultFinishLoading.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { view, _, scrollY, _, oldScrollY ->
backgroundPosterHolder.translationY = -scrollY.toFloat() * 0.8f
})
redirectToPlay.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) return@setOnFocusChangeListener
@ -284,13 +262,14 @@ class ResultFragmentTv : Fragment() {
binding?.apply {
val views = listOf(
resultPlayMovie,
resultPlaySeries,
resultResumeSeries,
resultPlayTrailer,
resultPlayMovieButton,
resultPlaySeriesButton,
resultResumeSeriesButton,
resultPlayTrailerButton,
resultBookmarkButton,
resultFavoriteButton,
resultSubscribeButton
resultSubscribeButton,
resultSearchButton
)
for (requestView in views) {
if (!requestView.isVisible) continue
@ -299,11 +278,6 @@ class ResultFragmentTv : Fragment() {
}
}
// parallax on background
resultFinishLoading.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
backgroundPosterHolder.translationY = -scrollY.toFloat() * 0.8f
})
redirectToEpisodes.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) return@setOnFocusChangeListener
toggleEpisodes(true)
@ -313,7 +287,7 @@ class ResultFragmentTv : Fragment() {
resultSeasonSelection,
resultRangeSelection,
resultEpisodes,
resultPlayTrailer,
resultPlayTrailerButton,
)
for (requestView in views) {
if (!requestView.isShown) continue
@ -322,6 +296,45 @@ class ResultFragmentTv : Fragment() {
}
}
mapOf(
resultPlayMovieButton to resultPlayMovieText,
resultPlaySeriesButton to resultPlaySeriesText,
resultResumeSeriesButton to resultResumeSeriesText,
resultPlayTrailerButton to resultPlayTrailerText,
resultBookmarkButton to resultBookmarkText,
resultFavoriteButton to resultFavoriteText,
resultSubscribeButton to resultSubscribeText,
resultSearchButton to resultSearchText,
resultEpisodesShowButton to resultEpisodesShowText
).forEach { (button , text) ->
button.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) {
text.isSelected = false
return@setOnFocusChangeListener
}
text.isSelected = true
if (button.tag == context?.getString(R.string.tv_no_focus_tag)){
resultFinishLoading.scrollTo(0,0)
}
when (button.id) {
R.id.result_episodes_show_button -> {
toggleEpisodes(true)
}
else -> {
toggleEpisodes(false)
}
}
}
}
resultEpisodesShowButton.setOnClickListener {
// toggle, to make it more touch accessible just in case someone thinks that a
// tv layout is better but is using a touch device
toggleEpisodes(!episodeHolderTv.isVisible)
}
resultEpisodes.setLinearListLayout(
isHorizontal = false,
nextUp = FOCUS_SELF,
@ -430,9 +443,9 @@ class ResultFragmentTv : Fragment() {
val aboveCast = listOf(
binding?.resultEpisodesShow,
binding?.resultBookmarkButton,
binding?.resultFavoriteButton,
binding?.resultSubscribeButton,
binding?.resultBookmark,
binding?.resultFavorite,
binding?.resultSubscribe,
).firstOrNull {
it?.isVisible == true
}
@ -443,8 +456,15 @@ class ResultFragmentTv : Fragment() {
observeNullable(viewModel.resumeWatching) { resume ->
binding?.apply {
// > resultResumeSeries is visible when not null
if (resume == null) {
resultResumeSeries.isVisible = false
return@observeNullable
}
// show progress no matter if series or movie
resume?.progress?.let { progress ->
resume.progress?.let { progress ->
resultResumeSeriesProgressText.setText(progress.progressLeft)
resultResumeSeriesProgress.apply {
isVisible = true
@ -456,37 +476,24 @@ class ResultFragmentTv : Fragment() {
resultResumeProgressHolder.isVisible = false
}
// if movie then hide both as movie button is
// always visible on movies, this is done in movie observe
if (resume?.isMovie == true) {
resultPlaySeries.isVisible = false
resultResumeSeries.isVisible = false
return@observeNullable
}
// if series then
// > resultPlaySeries is visible when null
// > resultResumeSeries is visible when not null
if (resume == null) {
resultPlaySeries.isVisible = true
resultResumeSeries.isVisible = false
return@observeNullable
}
resultPlayMovie.isVisible = false
resultPlaySeries.isVisible = false
resultResumeSeries.isVisible = true
focusPlayButton()
// Stops last button right focus if it is a movie
if (resume.isMovie)
resultSearchButton.nextFocusRightId = R.id.result_search_Button
resultResumeSeries.text =
if (resume.isMovie) context?.getString(R.string.play_movie_button) else context?.getNameFull(
null, // resume.result.name, we don't want episode title
resume.result.episode,
resume.result.season
)
resultResumeSeriesText.text =
when {
resume.isMovie -> context?.getString(R.string.resume)
resume.result.season != null ->
"${getString(R.string.season_short)}${resume.result.season}:${getString(R.string.episode_short)}${resume.result.episode}"
else -> "${getString(R.string.episode)}${resume.result.episode}"
}
resultResumeSeries.setOnClickListener {
resultResumeSeriesButton.setOnClickListener {
viewModel.handleAction(
EpisodeClickEvent(
storedData.playerAction, //?: ACTION_PLAY_EPISODE_IN_PLAYER,
@ -495,7 +502,7 @@ class ResultFragmentTv : Fragment() {
)
}
resultResumeSeries.setOnLongClickListener {
resultResumeSeriesButton.setOnLongClickListener {
viewModel.handleAction(
EpisodeClickEvent(ACTION_SHOW_OPTIONS, resume.result)
)
@ -509,9 +516,9 @@ class ResultFragmentTv : Fragment() {
context?.updateHasTrailers()
if (!LoadResponse.isTrailersEnabled) return@observe
val trailers = trailersLinks.flatMap { it.mirros }
binding?.resultPlayTrailer?.apply {
isGone = trailers.isEmpty()
setOnClickListener {
binding?.apply {
resultPlayTrailer.isGone = trailers.isEmpty()
resultPlayTrailerButton.setOnClickListener {
if (trailers.isEmpty()) return@setOnClickListener
activity.navigate(
R.id.global_to_navigation_player, GeneratorPlayer.newInstance(
@ -526,24 +533,38 @@ class ResultFragmentTv : Fragment() {
}
observe(viewModel.watchStatus) { watchType ->
binding?.resultBookmarkButton?.apply {
setText(watchType.stringRes)
binding?.apply {
resultBookmarkText.setText(watchType.stringRes)
resultBookmarkButton.apply {
val drawable = if (watchType.stringRes == R.string.type_none) {
R.drawable.outline_bookmark_add_24
} else {
R.drawable.ic_baseline_bookmark_24
}
setIconResource(drawable)
setOnClickListener { view ->
activity?.showBottomDialog(
WatchType.values().map { view.context.getString(it.stringRes) }.toList(),
WatchType.entries.map { view.context.getString(it.stringRes) }.toList(),
watchType.ordinal,
view.context.getString(R.string.action_add_to_bookmarks),
showApply = false,
{}) {
viewModel.updateWatchStatus(WatchType.values()[it], context)
viewModel.updateWatchStatus(WatchType.entries[it], context)
}
}
}
}
}
observeNullable(viewModel.favoriteStatus) { isFavorite ->
binding?.resultFavorite?.isVisible = isFavorite != null
binding?.resultFavoriteButton?.apply {
isVisible = isFavorite != null
if (isFavorite == null) return@observeNullable
val drawable = if (isFavorite) {
@ -552,14 +573,8 @@ class ResultFragmentTv : Fragment() {
R.drawable.ic_baseline_favorite_border_24
}
val text = if (isFavorite) {
R.string.action_remove_from_favorites
} else {
R.string.action_add_to_favorites
}
setIconResource(drawable)
setText(text)
setOnClickListener {
viewModel.toggleFavoriteStatus(context) { newStatus: Boolean? ->
if (newStatus == null) return@toggleFavoriteStatus
@ -576,11 +591,21 @@ class ResultFragmentTv : Fragment() {
}
}
}
binding?.resultFavoriteText?.apply {
val text = if (isFavorite == true) {
R.string.unfavorite
} else {
R.string.favorite
}
setText(text)
}
}
observeNullable(viewModel.subscribeStatus) { isSubscribed ->
binding?.resultSubscribe?.isVisible = isSubscribed != null && requireContext().isEmulatorSettings()
binding?.resultSubscribeButton?.apply {
isVisible = isSubscribed != null && context.isEmulatorSettings()
if (isSubscribed == null) return@observeNullable
val drawable = if (isSubscribed) {
@ -589,14 +614,8 @@ class ResultFragmentTv : Fragment() {
R.drawable.baseline_notifications_none_24
}
val text = if (isSubscribed) {
R.string.action_unsubscribe
} else {
R.string.action_subscribe
}
setIconResource(drawable)
setText(text)
setOnClickListener {
viewModel.toggleSubscriptionStatus(context) { newStatus: Boolean? ->
if (newStatus == null) return@toggleSubscriptionStatus
@ -614,32 +633,47 @@ class ResultFragmentTv : Fragment() {
CommonActivity.showToast(txt(message, name), Toast.LENGTH_SHORT)
}
}
binding?.resultSubscribeText?.apply {
val text = if (isSubscribed) {
R.string.action_unsubscribe
} else {
R.string.action_subscribe
}
setText(text)
}
}
}
observeNullable(viewModel.movie) { data ->
if (data == null) return@observeNullable
binding?.apply {
resultPlayMovie.isVisible = data is Resource.Success
resultPlaySeries.isVisible = data == null
seriesHolder.isVisible = data == null
resultEpisodesShow.isVisible = data == null
resultPlayMovie.isVisible = (data is Resource.Success) && !comingSoon
resultPlaySeries.isVisible = false
resultEpisodesShow.isVisible = false
(data as? Resource.Success)?.value?.let { (text, ep) ->
resultPlayMovie.setText(text)
resultPlayMovie.setOnClickListener {
//resultPlayMovieText.setText(text)
resultPlayMovieButton.setOnClickListener {
viewModel.handleAction(
EpisodeClickEvent(ACTION_CLICK_DEFAULT, ep)
)
}
resultPlayMovie.setOnLongClickListener {
resultPlayMovieButton.setOnLongClickListener {
viewModel.handleAction(
EpisodeClickEvent(ACTION_SHOW_OPTIONS, ep)
)
return@setOnLongClickListener true
}
focusPlayButton()
//focusPlayButton()
resultPlayMovieButton.requestFocus()
// Stops last button right focus
resultSearchButton.nextFocusRightId = R.id.result_search_Button
}
}
//focusPlayButton()
}
observeNullable(viewModel.selectPopup) { popup ->
@ -736,19 +770,26 @@ class ResultFragmentTv : Fragment() {
// Used to request focus the first time the episodes are loaded.
var hasLoadedEpisodesOnce = false
observeNullable(viewModel.episodes) { episodes ->
if (episodes == null) return@observeNullable
binding?.apply {
resultEpisodes.isVisible = episodes is Resource.Success
resultPlayMovie.isVisible = false
resultPlaySeries.isVisible = true && !comingSoon
resultEpisodes.isVisible = true && !comingSoon
resultEpisodesShow.isVisible = true && !comingSoon
// resultEpisodeLoading.isVisible = episodes is Resource.Loading
if (episodes is Resource.Success) {
val first = episodes.value.firstOrNull()
if (first != null) {
resultPlaySeries.text = context?.getNameFull(
null, // resume.result.name, we don't want episode title
first.episode,
first.season
)
resultPlaySeries.setOnClickListener {
resultPlaySeriesText.text = //"${getString(R.string.season_short)}${first.season}:${getString(R.string.episode_short)}${first.episode}"
when {
first.season != null ->
"${getString(R.string.season_short)}${first.season}:${getString(R.string.episode_short)}${first.episode}"
else -> "${getString(R.string.episode)} ${first.episode}"
}
resultPlaySeriesButton.setOnClickListener {
viewModel.handleAction(
EpisodeClickEvent(
ACTION_CLICK_DEFAULT,
@ -756,7 +797,7 @@ class ResultFragmentTv : Fragment() {
)
)
}
resultPlaySeries.setOnLongClickListener {
resultPlaySeriesButton.setOnLongClickListener {
viewModel.handleAction(
EpisodeClickEvent(ACTION_SHOW_OPTIONS, first)
)
@ -765,6 +806,7 @@ class ResultFragmentTv : Fragment() {
if (!hasLoadedEpisodesOnce) {
hasLoadedEpisodesOnce = true
focusPlayButton()
resultPlaySeries.requestFocus()
}
}
@ -826,6 +868,7 @@ class ResultFragmentTv : Fragment() {
resultMetaYear.setText(d.yearText)
resultMetaDuration.setText(d.durationText)
resultMetaRating.setText(d.ratingText)
resultMetaStatus.setText(d.onGoingText)
resultMetaContentRating.setText(d.contentRatingText)
resultCastText.setText(d.actorsText)
resultNextAiring.setText(d.nextAiringEpisode)
@ -859,8 +902,12 @@ class ResultFragmentTv : Fragment() {
radius = 0,
errorImageDrawable = error
)
resultComingSoon.isVisible = d.comingSoon
comingSoon = d.comingSoon
resultTvComingSoon.isVisible = d.comingSoon
resultPlayMovie.isGone = d.comingSoon
resultPlaySeries.isGone = d.comingSoon
resultDataHolder.isGone = d.comingSoon
UIHelper.populateChips(resultTag, d.tags)
resultCastItems.isGone = d.actors.isNullOrEmpty()
(resultCastItems.adapter as? ActorAdaptor)?.updateList(
@ -871,6 +918,10 @@ class ResultFragmentTv : Fragment() {
// If there is no rating to display, we don't want an empty gap
resultMetaContentRating.width = 0
}
resultSearchButton.setOnClickListener {
QuickSearchFragment.pushSearch(activity, d.title)
}
}
is Resource.Loading -> {

View file

@ -20,6 +20,7 @@ import com.lagradost.cloudstream3.APIHolder.apis
import com.lagradost.cloudstream3.APIHolder.getId
import com.lagradost.cloudstream3.APIHolder.unixTime
import com.lagradost.cloudstream3.APIHolder.unixTimeMS
import com.lagradost.cloudstream3.AcraApplication.Companion.context
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
import com.lagradost.cloudstream3.CommonActivity.activity
import com.lagradost.cloudstream3.CommonActivity.getCastSession
@ -31,6 +32,7 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.isMovie
import com.lagradost.cloudstream3.metaproviders.SyncRedirector
import com.lagradost.cloudstream3.mvvm.*
import com.lagradost.cloudstream3.syncproviders.AccountManager
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.secondsToReadable
import com.lagradost.cloudstream3.syncproviders.SyncAPI
import com.lagradost.cloudstream3.syncproviders.providers.Kitsu
import com.lagradost.cloudstream3.syncproviders.providers.SimklApi
@ -261,8 +263,7 @@ fun LoadResponse.toResultData(repo: APIRepository): ResultData {
metaText =
if (repo.providerType == ProviderType.MetaProvider) txt(R.string.provider_info_meta) else null,
durationText = if (dur == null || dur <= 0) null else txt(
R.string.duration_format,
dur
secondsToReadable(dur * 60, "0 mins")
),
onGoingText = if (this is EpisodeResponse) {
txt(
@ -2464,7 +2465,7 @@ class ResultViewModel2 : ViewModel() {
ResumeProgress(
progress = (viewPos.position / 1000).toInt(),
maxProgress = (viewPos.duration / 1000).toInt(),
txt(R.string.resume_time_left, (viewPos.duration - viewPos.position) / (60_000))
txt(R.string.resume_remaining, secondsToReadable(((viewPos.duration - viewPos.position) / 1_000).toInt(), "0 mins"))
)
}

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M240,760L240,800Q240,817 228.5,828.5Q217,840 200,840Q183,840 171.5,828.5Q160,817 160,800L160,160Q160,143 171.5,131.5Q183,120 200,120Q217,120 228.5,131.5Q240,143 240,160L240,200L320,200L320,160Q320,143 331.5,131.5Q343,120 360,120L600,120Q617,120 628.5,131.5Q640,143 640,160L640,200L720,200L720,160Q720,143 731.5,131.5Q743,120 760,120Q777,120 788.5,131.5Q800,143 800,160L800,800Q800,817 788.5,828.5Q777,840 760,840Q743,840 731.5,828.5Q720,817 720,800L720,760L640,760L640,800Q640,817 628.5,828.5Q617,840 600,840L360,840Q343,840 331.5,828.5Q320,817 320,800L320,760L240,760ZM240,680L320,680L320,600L240,600L240,680ZM240,520L320,520L320,440L240,440L240,520ZM240,360L320,360L320,280L240,280L240,360ZM640,680L720,680L720,600L640,600L640,680ZM640,520L720,520L720,440L640,440L640,520ZM640,360L720,360L720,280L640,280L640,360Z"/>
</vector>

View file

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="m8.46,5l0,14l11,-7l-11,-7z"
android:strokeLineJoin="round"
android:strokeWidth="0.006"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="m8.46,5l0,14l11,-7l-11,-7z"/>
<path
android:fillColor="@android:color/white"
android:pathData="M4.92,5.04h2.31v13.98h-2.31z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M17,11v6.97l-5,-2.14l-5,2.14V5h6V3H7C5.9,3 5,3.9 5,5v16l7,-3l7,3V11H17zM21,7h-2v2h-2V7h-2V5h2V3h2v2h2V7z"/>
</vector>

View file

@ -3,13 +3,13 @@
<item android:state_focused="true">
<shape android:shape="rectangle">
<solid android:color="?attr/white" />
<corners android:radius="3dp"/>
<corners android:radius="@dimen/rounded_image_radius"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="@color/white_attr_20" />
<corners android:radius="3dp"/>
<corners android:radius="@dimen/rounded_image_radius"/>
</shape>
</item>
</selector>

View file

@ -3,7 +3,7 @@
<item android:state_focused="true">
<shape android:shape="rectangle">
<solid android:color="?attr/white" />
<corners android:radius="3dp"/>
<corners android:radius="@dimen/rounded_image_radius"/>
</shape>
</item>
</selector>

View file

@ -17,7 +17,6 @@
android:layout_width="100dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:focusable="true"
android:padding="5dp">
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
<FrameLayout

View file

@ -157,6 +157,7 @@
android:id="@+id/home_preview_hidden_prev_focus"
android:layout_width="1dp"
android:layout_height="1dp"
android:tag="@string/tv_no_focus_tag"
android:focusable="false" />
<com.google.android.material.button.MaterialButton
@ -189,6 +190,7 @@
android:id="@+id/home_preview_hidden_next_focus"
android:layout_width="1dp"
android:layout_height="1dp"
android:tag="@string/tv_no_focus_tag"
android:focusable="false" />
</LinearLayout>
</LinearLayout>

View file

@ -412,7 +412,7 @@
android:foreground="@drawable/outline_drawable"
android:maxLength="1000"
android:nextFocusUp="@id/result_back"
android:nextFocusDown="@id/result_bookmark_button"
android:nextFocusDown="@id/result_bookmark_Button"
android:paddingTop="5dp"
android:textColor="?attr/textColor"
android:textSize="15sp"
@ -474,7 +474,7 @@
android:fadingEdge="horizontal"
android:focusable="false"
android:focusableInTouchMode="false"
android:nextFocusUp="@id/result_bookmark_button"
android:nextFocusUp="@id/result_bookmark_Button"
android:nextFocusDown="@id/result_play_movie"
android:orientation="horizontal"
android:paddingTop="5dp"
@ -580,7 +580,7 @@
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layout_marginBottom="10dp"
android:nextFocusUp="@id/result_bookmark_button"
android:nextFocusUp="@id/result_bookmark_Button"
android:nextFocusDown="@id/result_download_movie"
android:text="@string/play_movie_button"
android:visibility="visible"
@ -658,7 +658,7 @@
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layout_marginBottom="10dp"
android:nextFocusUp="@id/result_bookmark_button"
android:nextFocusUp="@id/result_bookmark_Button"
android:nextFocusDown="@id/result_download_movie"
android:text="@string/resume"
android:visibility="visible"
@ -674,7 +674,7 @@
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layout_marginBottom="10dp"
android:nextFocusUp="@id/result_bookmark_button"
android:nextFocusUp="@id/result_bookmark_Button"
android:nextFocusDown="@id/result_download_movie"
android:text="@string/next_episode"
android:visibility="gone"

View file

@ -78,6 +78,30 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
</LinearLayout>
</com.facebook.shimmer.ShimmerFrameLayout>
<FrameLayout
android:id="@+id/background_poster_holder"
android:layout_width="match_parent"
android:layout_height="275dp"
android:visibility="visible">
<com.lagradost.cloudstream3.utils.PercentageCropImageView
android:id="@+id/background_poster"
android:layout_width="match_parent"
android:layout_height="275dp"
android:layout_gravity="center"
android:alpha="0.8"
android:scaleType="matrix"
tools:src="@drawable/profile_bg_dark_blue" >
</com.lagradost.cloudstream3.utils.PercentageCropImageView>
<ImageView
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_gravity="bottom"
android:src="@drawable/background_shadow">
</ImageView>
</FrameLayout>
<LinearLayout
android:id="@+id/result_loading_error"
@ -124,31 +148,6 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:textColor="?attr/textColor" />
</LinearLayout>
<FrameLayout
android:id="@+id/background_poster_holder"
android:layout_width="match_parent"
android:layout_height="250dp"
android:visibility="visible">
<com.lagradost.cloudstream3.utils.PercentageCropImageView
android:id="@+id/background_poster"
android:layout_width="match_parent"
android:layout_height="275dp"
android:layout_gravity="center"
android:alpha="0.8"
android:scaleType="matrix"
tools:src="@drawable/profile_bg_dark_blue" >
</com.lagradost.cloudstream3.utils.PercentageCropImageView>
<ImageView
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_gravity="bottom"
android:src="@drawable/background_shadow">
</ImageView>
</FrameLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/result_finish_loading"
android:layout_width="match_parent"
@ -165,7 +164,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="175dp">
android:layout_marginTop="225dp">
<TextView
android:id="@+id/result_title"
@ -175,7 +174,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:gravity="center_vertical"
android:singleLine="true"
android:textColor="?attr/textColor"
android:textSize="20sp"
android:textSize="25sp"
android:textStyle="bold"
tools:text="The Perfect Run The Perfect Run" />
@ -221,157 +220,289 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:textStyle="normal"
tools:text="5d 3h 30m" />
</LinearLayout>
<LinearLayout
android:id="@+id/result_resume_progress_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="horizontal"
android:visibility="gone"
tools:visibility="visible">
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/result_resume_series_progress"
app:trackCornerRadius="50dp"
android:layout_width="100dp"
android:layout_height="20dp"
android:layout_gravity="end|center_vertical"
android:layout_weight="1"
android:indeterminate="false"
android:max="100"
android:paddingEnd="10dp"
android:progress="0"
android:progressBackgroundTint="?attr/colorPrimary"
tools:progress="50"
tools:visibility="visible"
tools:ignore="RtlSymmetry" />
<TextView
android:id="@+id/result_resume_series_progress_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textColor="?attr/grayTextColor"
tools:ignore="RtlSymmetry"
tools:text="69m remaining" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/result_play_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="5dp"
android:descendantFocusability="afterDescendants"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:id="@+id/result_play_movie"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_play_movie_button"
android:focusable="true"
style="@style/ResultSmallButtonTV"
app:iconPadding="0dp"
app:icon="@drawable/ic_baseline_play_arrow_24"
android:nextFocusUp="@id/result_play_movie_button"
android:nextFocusDown="@id/result_description"
android:tag="@string/tv_no_focus_tag">
</com.google.android.material.button.MaterialButton>
<TextView
android:id="@+id/result_play_movie_text"
style="@style/ResultMarqueeButtonText"
android:text="@string/movies_singular" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:id="@+id/result_play_series"
android:visibility="gone"
tools:visibility="visible"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_play_series_button"
android:focusable="true"
style="@style/ResultSmallButtonTV"
app:iconPadding="0dp"
app:icon="@drawable/ic_baseline_play_arrow_24"
android:nextFocusUp="@id/result_play_series_button"
android:nextFocusDown="@id/result_description"
android:tag="@string/tv_no_focus_tag">
</com.google.android.material.button.MaterialButton>
<TextView
android:id="@+id/result_play_series_text"
style="@style/ResultMarqueeButtonText"
android:text="@string/episode" />
</LinearLayout>
<LinearLayout
android:id="@+id/result_resume_series"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_resume_series_button"
android:focusable="true"
style="@style/ResultSmallButtonTV"
app:iconPadding="0dp"
app:icon="@drawable/ic_baseline_resume_arrow2"
android:nextFocusUp="@id/result_resume_series_button"
android:nextFocusDown="@id/result_description"
android:tag="@string/tv_no_focus_tag">
</com.google.android.material.button.MaterialButton>
<TextView
android:id="@+id/result_resume_series_text"
style="@style/ResultMarqueeButtonText"
android:text="@string/resume" />
</LinearLayout>
<LinearLayout
android:id="@+id/result_play_trailer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_play_trailer_button"
android:focusable="true"
style="@style/ResultSmallButtonTV"
app:iconPadding="0dp"
app:icon="@drawable/ic_baseline_film_roll_24"
android:nextFocusUp="@id/result_play_trailer_button"
android:nextFocusDown="@id/result_description"
android:tag="@string/tv_no_focus_tag">
</com.google.android.material.button.MaterialButton>
<TextView
android:id="@+id/result_play_trailer_text"
style="@style/ResultMarqueeButtonText"
android:text="@string/play_trailer_button" />
</LinearLayout>
<LinearLayout
android:id="@+id/result_bookmark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_bookmark_Button"
android:focusable="true"
style="@style/ResultSmallButtonTV"
app:iconPadding="0dp"
app:icon="@drawable/outline_bookmark_add_24"
android:nextFocusUp="@id/result_bookmark_Button"
android:nextFocusDown="@id/result_description"
android:tag="@string/tv_no_focus_tag">
</com.google.android.material.button.MaterialButton>
<TextView
android:id="@+id/result_bookmark_text"
style="@style/ResultMarqueeButtonText"
android:text="@string/type_none" />
</LinearLayout>
<LinearLayout
android:id="@+id/result_favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_favorite_Button"
android:focusable="true"
style="@style/ResultSmallButtonTV"
app:iconPadding="0dp"
app:icon="@drawable/ic_baseline_favorite_border_24"
android:nextFocusUp="@id/result_favorite_Button"
android:nextFocusDown="@id/result_description"
android:tag="@string/tv_no_focus_tag">
</com.google.android.material.button.MaterialButton>
<TextView
android:id="@+id/result_favorite_Text"
style="@style/ResultMarqueeButtonText"
android:text="@string/favorite" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:id="@+id/result_subscribe"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_subscribe_Button"
android:focusable="true"
style="@style/ResultSmallButtonTV"
app:iconPadding="0dp"
app:icon="@drawable/baseline_notifications_none_24"
android:nextFocusUp="@id/result_subscribe_Button"
android:nextFocusDown="@id/result_description"
android:tag="@string/tv_no_focus_tag">
</com.google.android.material.button.MaterialButton>
<TextView
android:id="@+id/result_subscribe_text"
style="@style/ResultMarqueeButtonText"
android:text="@string/action_subscribe" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:id="@+id/result_search"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_search_Button"
android:focusable="true"
style="@style/ResultSmallButtonTV"
app:iconPadding="0dp"
app:icon="@drawable/search_icon"
android:nextFocusUp="@id/result_search_Button"
android:nextFocusDown="@id/result_description"
android:tag="@string/tv_no_focus_tag">
</com.google.android.material.button.MaterialButton>
<TextView
android:id="@+id/result_search_text"
style="@style/ResultMarqueeButtonText"
android:text="@string/title_search" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:id="@+id/result_episodes_show"
android:visibility="gone"
tools:visibility="visible"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_episodes_show_button"
android:focusable="true"
style="@style/ResultSmallButtonTV"
app:iconPadding="0dp"
app:icon="@drawable/ic_baseline_sort_24"
android:nextFocusUp="@id/result_episodes_show_button"
android:nextFocusRight="@id/redirect_to_episodes"
android:nextFocusDown="@id/result_description"
android:tag="@string/tv_no_focus_tag">
</com.google.android.material.button.MaterialButton>
<TextView
android:id="@+id/result_episodes_show_text"
style="@style/ResultMarqueeButtonText"
android:text="@string/episodes" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="10dp">
<LinearLayout
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_weight="0"
android:orientation="vertical">
<LinearLayout
android:id="@+id/result_movie_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:animateLayoutChanges="true"
android:orientation="vertical"
tools:visibility="visible">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_play_movie"
style="@style/ResultButtonTV"
android:nextFocusRight="@id/result_description"
android:nextFocusUp="@id/result_play_movie"
android:nextFocusDown="@id/result_play_series"
android:text="@string/play_movie_button"
android:visibility="visible"
app:icon="@drawable/ic_baseline_play_arrow_24" />
<LinearLayout
android:id="@+id/series_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_play_series"
style="@style/ResultButtonTV"
android:nextFocusRight="@id/result_description"
android:nextFocusUp="@id/result_play_movie"
android:nextFocusDown="@id/result_resume_series"
android:text="@string/play_episode"
android:visibility="visible"
app:icon="@drawable/ic_baseline_play_arrow_24" />
<com.google.android.material.button.MaterialButton
android:id="@+id/result_resume_series"
style="@style/ResultButtonTV"
android:nextFocusRight="@id/result_description"
android:nextFocusUp="@id/result_play_series"
android:nextFocusDown="@id/result_play_trailer"
android:text="@string/resume"
android:visibility="visible"
app:icon="@drawable/ic_baseline_play_arrow_24" />
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/result_play_trailer"
style="@style/ResultButtonTV"
android:nextFocusRight="@id/result_description"
android:nextFocusUp="@id/result_resume_series"
android:nextFocusDown="@id/result_bookmark_button"
android:text="@string/play_trailer_button"
android:visibility="gone"
app:icon="@drawable/ic_baseline_play_arrow_24"
tools:visibility="visible" />
<!-- <com.lagradost.cloudstream3.ui.download.button.DownloadButton
android:visibility="gone"
android:id="@+id/download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:minWidth="250dp"
app:download_layout="@layout/download_button_layout" />
-->
<com.google.android.material.button.MaterialButton
android:id="@+id/result_bookmark_button"
style="@style/ResultButtonTV"
android:nextFocusRight="@id/result_description"
android:nextFocusUp="@id/result_play_trailer"
android:nextFocusDown="@id/result_favorite_button"
android:text="@string/type_none"
android:visibility="visible"
app:icon="@drawable/ic_baseline_bookmark_24" />
<com.google.android.material.button.MaterialButton
android:id="@+id/result_favorite_button"
style="@style/ResultButtonTV"
android:nextFocusRight="@id/result_description"
android:nextFocusUp="@id/result_bookmark_button"
android:nextFocusDown="@id/result_subscribe_button"
android:text="@string/action_add_to_favorites"
android:visibility="visible"
app:icon="@drawable/ic_baseline_favorite_border_24" />
<com.google.android.material.button.MaterialButton
android:id="@+id/result_subscribe_button"
style="@style/ResultButtonTV"
android:nextFocusRight="@id/result_description"
android:nextFocusUp="@id/result_favorite_button"
android:nextFocusDown="@id/result_episodes_show"
android:text="@string/action_subscribe"
android:visibility="visible"
app:icon="@drawable/ic_baseline_favorite_border_24" />
<com.google.android.material.button.MaterialButton
android:id="@+id/result_episodes_show"
style="@style/ResultButtonTV"
android:nextFocusRight="@id/redirect_to_episodes"
android:nextFocusUp="@id/result_subscribe_button"
android:nextFocusDown="@id/result_cast_items"
android:text="@string/episodes"
android:visibility="visible"
app:icon="@drawable/ic_baseline_sort_24"
tools:visibility="visible" />
<View
android:id="@+id/redirect_to_episodes"
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true" />
<View
android:id="@+id/redirect_to_play"
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true" />
</LinearLayout>
</LinearLayout>
android:layout_marginTop="10dp"
android:baselineAligned="false">
<LinearLayout
android:id="@+id/right_layout"
@ -382,7 +513,8 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/linearLayout2"
app:layout_constraintTop_toTopOf="parent">
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UselessParent">
<com.lagradost.cloudstream3.widget.FlowLayout
android:layout_width="match_parent"
@ -439,8 +571,8 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:foreground="@drawable/outline_drawable"
android:maxLines="7"
android:focusable="true"
android:nextFocusUp="@id/result_back"
android:nextFocusDown="@id/result_bookmark_button"
android:nextFocusUp="@id/result_play_parent"
android:nextFocusDown="@id/result_cast_items"
android:padding="5dp"
android:requiresFadingEdge="vertical"
android:textColor="?attr/textColor"
@ -450,59 +582,8 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
<com.google.android.material.chip.ChipGroup
android:id="@+id/result_tag"
style="@style/ChipParent"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone">
<LinearLayout
android:id="@+id/result_resume_progress_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="horizontal"
android:visibility="gone"
tools:visibility="visible">
<androidx.core.widget.ContentLoadingProgressBar
android:id="@+id/result_resume_series_progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_gravity="end|center_vertical"
android:layout_weight="1"
android:indeterminate="false"
android:max="100"
android:paddingEnd="10dp"
android:progress="0"
android:progressBackgroundTint="?attr/colorPrimary"
android:visibility="gone"
tools:progress="50"
tools:visibility="visible" />
<TextView
android:id="@+id/result_resume_series_progress_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="0"
android:gravity="center"
android:maxLines="1"
android:paddingEnd="5dp"
android:textColor="?attr/grayTextColor"
android:visibility="gone"
tools:ignore="RtlSymmetry"
tools:text="69m remaining" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
</LinearLayout>
@ -513,10 +594,8 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:descendantFocusability="afterDescendants"
android:fadingEdge="horizontal"
android:focusable="false"
android:focusableInTouchMode="false"
android:nextFocusUp="@id/result_episodes_show"
android:nextFocusDown="@id/result_recommendations_filter_selection"
android:nextFocusUp="@id/result_description"
android:nextFocusDown="@id/result_recommendations_list"
android:orientation="horizontal"
android:paddingTop="5dp"
android:requiresFadingEdge="horizontal"
@ -525,8 +604,23 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
tools:listitem="@layout/cast_item"
tools:visibility="visible" />
<TextView
android:id="@+id/result_tv_coming_soon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingTop="50dp"
android:text="@string/coming_soon"
android:textColor="?attr/textColor"
android:textSize="20sp"
android:textStyle="bold"
tools:visibility="visible"
android:visibility="gone" />
<LinearLayout
android:id="@+id/result_recommendations_holder"
android:descendantFocusability="afterDescendants"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
@ -540,7 +634,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:layout_marginEnd="10dp"
android:nextFocusUp="@id/result_cast_items"
android:nextFocusDown="@id/result_recommendations_list"
android:descendantFocusability="afterDescendants"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="2"
@ -563,7 +657,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:layout_height="wrap_content"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
android:nextFocusUp="@id/result_recommendations_filter_selection"
android:nextFocusUp="@id/result_cast_items"
android:orientation="vertical"
app:spanCount="8"
tools:listitem="@layout/search_result_grid" />
@ -576,7 +670,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:layout_height="match_parent"
android:layout_gravity="end"
android:visibility="gone"
tools:visibility="visible">
tools:visibility="invisible">
<!--
@ -765,152 +859,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<!--
<LinearLayout
android:id="@+id/result_movie_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:animateLayoutChanges="true"
android:orientation="vertical"
tools:visibility="visible">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_play_movie"
style="@style/RegularButtonTV"
android:layout_width="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:minWidth="250dp"
android:nextFocusUp="@id/result_back"
android:nextFocusDown="@id/result_play_series"
android:text="@string/play_movie_button"
android:visibility="visible"
app:icon="@drawable/ic_baseline_play_arrow_24">
</com.google.android.material.button.MaterialButton>
<LinearLayout
android:id="@+id/series_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_play_series"
style="@style/RegularButtonTV"
android:layout_width="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:minWidth="250dp"
android:nextFocusUp="@id/result_play_movie"
android:nextFocusDown="@id/result_resume_series"
android:text="@string/play_episode"
android:visibility="visible"
app:icon="@drawable/ic_baseline_play_arrow_24"
tools:visibility="gone" />
<com.google.android.material.button.MaterialButton
android:id="@+id/result_resume_series"
style="@style/RegularButtonTV"
android:layout_width="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:minWidth="250dp"
android:nextFocusUp="@id/result_play_series"
android:nextFocusDown="@id/result_play_trailer"
android:text="@string/resume"
android:visibility="visible"
app:icon="@drawable/ic_baseline_play_arrow_24"
tools:visibility="gone" />
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/result_play_trailer"
style="@style/RegularButtonTV"
android:layout_width="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:minWidth="250dp"
android:nextFocusUp="@id/result_resume_series"
android:nextFocusDown="@id/result_bookmark_button"
android:text="@string/play_trailer_button"
android:visibility="gone"
app:icon="@drawable/ic_baseline_play_arrow_24"
tools:visibility="visible">
</com.google.android.material.button.MaterialButton>
<com.google.android.material.button.MaterialButton
android:id="@+id/result_bookmark_button"
style="@style/RegularButtonTV"
android:layout_width="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:minWidth="250dp"
android:nextFocusUp="@id/result_play_trailer"
android:nextFocusDown="@id/result_resume_series_button"
android:text="@string/type_none"
android:visibility="visible" />
<LinearLayout
android:id="@+id/result_resume_progress_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="horizontal"
android:visibility="gone"
tools:visibility="visible">
<androidx.core.widget.ContentLoadingProgressBar
android:id="@+id/result_resume_series_progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_gravity="end|center_vertical"
android:layout_weight="1"
android:indeterminate="false"
android:max="100"
android:paddingEnd="10dp"
android:progress="0"
android:progressBackgroundTint="?attr/colorPrimary"
android:visibility="visible"
tools:progress="50"
tools:visibility="visible" />
<TextView
android:id="@+id/result_resume_series_progress_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="0"
android:gravity="center"
android:maxLines="1"
android:paddingEnd="5dp"
android:textColor="?attr/grayTextColor"
tools:ignore="RtlSymmetry"
tools:text="69m remaining" />
</LinearLayout>
</LinearLayout>
-->
<androidx.cardview.widget.CardView
android:id="@+id/result_poster_holder"
android:layout_width="wrap_content"
@ -1067,70 +1016,47 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:visibility="gone"
app:icon="@drawable/ic_baseline_add_24" />
<!--<LinearLayout
android:id="@+id/result_resume_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="gone">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_next_series_button"
style="@style/WhiteButton"
android:layout_width="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layout_marginBottom="10dp"
android:nextFocusUp="@id/result_bookmark_button"
android:nextFocusDown="@id/result_download_movie"
android:text="@string/next_episode"
android:visibility="gone"
app:icon="@drawable/cast_ic_mini_controller_skip_next" />
</LinearLayout>
<LinearLayout
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_weight="0"
android:orientation="vertical">
<LinearLayout
android:id="@+id/result_movie_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:layout_gravity="start"
android:animateLayoutChanges="true"
android:orientation="vertical"
tools:visibility="visible">
<ImageView
android:id="@+id/result_resume_series_button"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/download"
android:nextFocusUp="@id/result_play_movie"
android:nextFocusDown="@id/result_season_selection"
android:src="@drawable/ic_baseline_play_arrow_24"
android:visibility="visible"
app:tint="?attr/white" />
<TextView
android:id="@+id/result_resume_series_title"
<LinearLayout
android:id="@+id/series_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textColor="?attr/textColor"
android:textSize="17sp"
android:textStyle="bold"
tools:text="S1E1 Episode 1" />
android:orientation="vertical">
<View
android:id="@+id/redirect_to_episodes"
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true" />
<View
android:id="@+id/redirect_to_play"
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>-->
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</FrameLayout>

View file

@ -533,18 +533,14 @@
android:id="@id/exo_position"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginStart="20dp"
android:gravity="end|center_vertical"
android:gravity="center"
android:includeFontPadding="false"
android:minWidth="50dp"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="normal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@id/player_pause_play"
app:layout_constraintStart_toEndOf="@id/player_pause_play"
tools:text="15:30" />
<FrameLayout

View file

@ -306,6 +306,7 @@
<string name="go_forward_30">+30</string>
<string name="delete_message" formatted="true">This will permanently delete %s\nAre you sure?</string>
<string name="resume_time_left" formatted="true">%dm\nremaining</string>
<string name="resume_remaining" formatted="true">%s\nremaining</string>
<string name="status_ongoing">Ongoing</string>
<string name="status_completed">Completed</string>
<string name="status">Status</string>
@ -745,7 +746,8 @@
<string name="rotate_video_desc">Display a toggle button for screen orientation</string>
<string name="auto_rotate_video_desc">Enable automatic switching of screen orientation based on video orientation</string>
<string name="auto_rotate_video">Auto rotate</string>
<string name="favorite">Favorite</string>
<string name="unfavorite">Unfavorite</string>
<!-- For Biometrics -->
<string name="biometric_authentication_title">Unlock CloudStream</string>
<string name="biometric_setting">Lock with Biometrics</string>
@ -758,4 +760,5 @@
<string name="biometric_warning">Your CloudStream data has been backed up now, although probability of this rare case is very low but all
devices behave differently, in case you get locked down from accessing the app in worst case scenario,
Clear the app data wholly and restore the backup. Any inconvenience if arrived is deeply regretted.</string>
</resources>

View file

@ -814,6 +814,35 @@
<item name="android:insetTop">0dp</item>
</style>
<style name="ResultSmallButtonTV">
<item name="android:tag">@string/tv_no_focus_tag</item>
<item name="android:stateListAnimator">@null</item>
<item name="strokeColor">@color/transparent</item>
<item name="backgroundTint">@null</item>
<item name="android:background">@drawable/player_button_tv_attr</item>
<item name="rippleColor">@color/white</item>
<item name="android:shadowColor">@color/transparent</item>
<item name="iconTint">@color/player_on_button_tv_attr</item>
<item name="iconGravity">textStart</item>
<item name="android:layout_width">60dp</item>
<item name="android:layout_height">40dp</item>
<item name="android:gravity">center</item>
<item name="android:layout_gravity">center</item>
<item name="android:layout_marginStart">4dp</item>
<item name="android:layout_marginEnd">4dp</item>
<item name="android:layout_marginBottom">4dp</item>
</style>
<style name="ResultMarqueeButtonText">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">top|center_horizontal</item>
<item name="android:singleLine">true</item>
<item name="android:scrollHorizontally">true</item>
<item name="android:marqueeRepeatLimit">marquee_forever</item>
<item name="android:ellipsize">marquee</item>
</style>
<style name="VideoButtonTV">
<item name="android:tag">@string/tv_no_focus_tag</item>
<item name="android:stateListAnimator">@null</item>