Merge remote-tracking branch 'origin/master' into batteryoptimization

This commit is contained in:
IndusAryan 2024-03-11 20:32:27 +05:30
commit 275ff38e93
20 changed files with 658 additions and 588 deletions

View file

@ -19,7 +19,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import android.widget.Toast import android.widget.Toast
import android.widget.Toast.LENGTH_LONG
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.IdRes import androidx.annotation.IdRes
@ -1189,7 +1188,25 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricAu
} }
if(isTrueTvSettings()) { 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 -> newLocalBinding.root.viewTreeObserver.addOnGlobalFocusChangeListener { _, newFocus ->
if (exceptionButtons.contains(newFocus?.id)) return@addOnGlobalFocusChangeListener
centerView(newFocus) centerView(newFocus)
} }
} }
@ -1220,8 +1237,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricAu
// hide background while authenticating, Sorry moms & dads 🙏 // hide background while authenticating, Sorry moms & dads 🙏
binding?.navHostFragment?.isInvisible = true binding?.navHostFragment?.isInvisible = true
} else {
showToast(R.string.phone_not_secured, LENGTH_LONG)
} }
} }

View file

@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
@ -57,14 +56,16 @@ class AccountSelectActivity : AppCompatActivity(), BiometricAuthenticator.Biomet
if (isTruePhone() && authEnabled) { if (isTruePhone() && authEnabled) {
if (deviceHasPasswordPinLock(this)) { if (deviceHasPasswordPinLock(this)) {
startBiometricAuthentication(this, R.string.biometric_authentication_title, false) startBiometricAuthentication(
this,
R.string.biometric_authentication_title,
false
)
BiometricAuthenticator.promptInfo?.let { BiometricAuthenticator.promptInfo?.let {
BiometricAuthenticator.biometricPrompt?.authenticate(it) BiometricAuthenticator.biometricPrompt?.authenticate(it)
} }
} }
} else {
showToast(R.string.phone_not_secured, Toast.LENGTH_LONG)
} }
} }

View file

@ -529,6 +529,7 @@ class HomeFragment : Fragment() {
super.onScrolled(recyclerView, dx, dy) 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.download.DownloadButtonSetup
import com.lagradost.cloudstream3.ui.player.ExtractorLinkGenerator import com.lagradost.cloudstream3.ui.player.ExtractorLinkGenerator
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer 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.getStoredData
import com.lagradost.cloudstream3.ui.result.ResultFragment.updateUIEvent import com.lagradost.cloudstream3.ui.result.ResultFragment.updateUIEvent
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_FOCUSED import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_FOCUSED
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.ui.settings.SettingsFragment.Companion.isEmulatorSettings 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.html
import com.lagradost.cloudstream3.utils.AppUtils.isRtl import com.lagradost.cloudstream3.utils.AppUtils.isRtl
import com.lagradost.cloudstream3.utils.AppUtils.loadCache 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). * Note that this will steal any focus if the episode loading is too slow (unlikely).
*/ */
private fun focusPlayButton() { private fun focusPlayButton() {
binding?.resultPlayMovie?.requestFocus() binding?.resultPlayMovieButton?.requestFocus()
binding?.resultPlaySeries?.requestFocus() binding?.resultPlaySeriesButton?.requestFocus()
binding?.resultResumeSeries?.requestFocus() binding?.resultResumeSeriesButton?.requestFocus()
} }
private fun setRecommendations(rec: List<SearchResponse>?, validApiName: String?) { private fun setRecommendations(rec: List<SearchResponse>?, validApiName: String?) {
@ -246,37 +246,15 @@ class ResultFragmentTv : Fragment() {
storedData.start storedData.start
) )
// ===== ===== ===== // ===== ===== =====
var comingSoon = false
binding?.apply { binding?.apply {
//episodesShadow.rotationX = 180.0f//if(episodesShadow.isRtl()) 180.0f else 0.0f //episodesShadow.rotationX = 180.0f//if(episodesShadow.isRtl()) 180.0f else 0.0f
val leftListener: View.OnFocusChangeListener = // parallax on background
View.OnFocusChangeListener { _, hasFocus -> resultFinishLoading.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { view, _, scrollY, _, oldScrollY ->
if (!hasFocus) return@OnFocusChangeListener backgroundPosterHolder.translationY = -scrollY.toFloat() * 0.8f
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
redirectToPlay.setOnFocusChangeListener { _, hasFocus -> redirectToPlay.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) return@setOnFocusChangeListener if (!hasFocus) return@setOnFocusChangeListener
@ -284,13 +262,14 @@ class ResultFragmentTv : Fragment() {
binding?.apply { binding?.apply {
val views = listOf( val views = listOf(
resultPlayMovie, resultPlayMovieButton,
resultPlaySeries, resultPlaySeriesButton,
resultResumeSeries, resultResumeSeriesButton,
resultPlayTrailer, resultPlayTrailerButton,
resultBookmarkButton, resultBookmarkButton,
resultFavoriteButton, resultFavoriteButton,
resultSubscribeButton resultSubscribeButton,
resultSearchButton
) )
for (requestView in views) { for (requestView in views) {
if (!requestView.isVisible) continue 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 -> redirectToEpisodes.setOnFocusChangeListener { _, hasFocus ->
if (!hasFocus) return@setOnFocusChangeListener if (!hasFocus) return@setOnFocusChangeListener
toggleEpisodes(true) toggleEpisodes(true)
@ -313,7 +287,7 @@ class ResultFragmentTv : Fragment() {
resultSeasonSelection, resultSeasonSelection,
resultRangeSelection, resultRangeSelection,
resultEpisodes, resultEpisodes,
resultPlayTrailer, resultPlayTrailerButton,
) )
for (requestView in views) { for (requestView in views) {
if (!requestView.isShown) continue 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( resultEpisodes.setLinearListLayout(
isHorizontal = false, isHorizontal = false,
nextUp = FOCUS_SELF, nextUp = FOCUS_SELF,
@ -430,9 +443,9 @@ class ResultFragmentTv : Fragment() {
val aboveCast = listOf( val aboveCast = listOf(
binding?.resultEpisodesShow, binding?.resultEpisodesShow,
binding?.resultBookmarkButton, binding?.resultBookmark,
binding?.resultFavoriteButton, binding?.resultFavorite,
binding?.resultSubscribeButton, binding?.resultSubscribe,
).firstOrNull { ).firstOrNull {
it?.isVisible == true it?.isVisible == true
} }
@ -443,8 +456,15 @@ class ResultFragmentTv : Fragment() {
observeNullable(viewModel.resumeWatching) { resume -> observeNullable(viewModel.resumeWatching) { resume ->
binding?.apply { binding?.apply {
// > resultResumeSeries is visible when not null
if (resume == null) {
resultResumeSeries.isVisible = false
return@observeNullable
}
// show progress no matter if series or movie // show progress no matter if series or movie
resume?.progress?.let { progress -> resume.progress?.let { progress ->
resultResumeSeriesProgressText.setText(progress.progressLeft) resultResumeSeriesProgressText.setText(progress.progressLeft)
resultResumeSeriesProgress.apply { resultResumeSeriesProgress.apply {
isVisible = true isVisible = true
@ -456,37 +476,24 @@ class ResultFragmentTv : Fragment() {
resultResumeProgressHolder.isVisible = false resultResumeProgressHolder.isVisible = false
} }
// if movie then hide both as movie button is resultPlayMovie.isVisible = false
// 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
}
resultPlaySeries.isVisible = false resultPlaySeries.isVisible = false
resultResumeSeries.isVisible = true resultResumeSeries.isVisible = true
focusPlayButton() focusPlayButton()
// Stops last button right focus if it is a movie
if (resume.isMovie)
resultSearchButton.nextFocusRightId = R.id.result_search_Button
resultResumeSeries.text = resultResumeSeriesText.text =
if (resume.isMovie) context?.getString(R.string.play_movie_button) else context?.getNameFull( when {
null, // resume.result.name, we don't want episode title resume.isMovie -> context?.getString(R.string.resume)
resume.result.episode, resume.result.season != null ->
resume.result.season "${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( viewModel.handleAction(
EpisodeClickEvent( EpisodeClickEvent(
storedData.playerAction, //?: ACTION_PLAY_EPISODE_IN_PLAYER, storedData.playerAction, //?: ACTION_PLAY_EPISODE_IN_PLAYER,
@ -495,7 +502,7 @@ class ResultFragmentTv : Fragment() {
) )
} }
resultResumeSeries.setOnLongClickListener { resultResumeSeriesButton.setOnLongClickListener {
viewModel.handleAction( viewModel.handleAction(
EpisodeClickEvent(ACTION_SHOW_OPTIONS, resume.result) EpisodeClickEvent(ACTION_SHOW_OPTIONS, resume.result)
) )
@ -509,9 +516,9 @@ class ResultFragmentTv : Fragment() {
context?.updateHasTrailers() context?.updateHasTrailers()
if (!LoadResponse.isTrailersEnabled) return@observe if (!LoadResponse.isTrailersEnabled) return@observe
val trailers = trailersLinks.flatMap { it.mirros } val trailers = trailersLinks.flatMap { it.mirros }
binding?.resultPlayTrailer?.apply { binding?.apply {
isGone = trailers.isEmpty() resultPlayTrailer.isGone = trailers.isEmpty()
setOnClickListener { resultPlayTrailerButton.setOnClickListener {
if (trailers.isEmpty()) return@setOnClickListener if (trailers.isEmpty()) return@setOnClickListener
activity.navigate( activity.navigate(
R.id.global_to_navigation_player, GeneratorPlayer.newInstance( R.id.global_to_navigation_player, GeneratorPlayer.newInstance(
@ -526,24 +533,38 @@ class ResultFragmentTv : Fragment() {
} }
observe(viewModel.watchStatus) { watchType -> observe(viewModel.watchStatus) { watchType ->
binding?.resultBookmarkButton?.apply { binding?.apply {
setText(watchType.stringRes) 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 -> setOnClickListener { view ->
activity?.showBottomDialog( activity?.showBottomDialog(
WatchType.values().map { view.context.getString(it.stringRes) }.toList(), WatchType.entries.map { view.context.getString(it.stringRes) }.toList(),
watchType.ordinal, watchType.ordinal,
view.context.getString(R.string.action_add_to_bookmarks), view.context.getString(R.string.action_add_to_bookmarks),
showApply = false, showApply = false,
{}) { {}) {
viewModel.updateWatchStatus(WatchType.values()[it], context) viewModel.updateWatchStatus(WatchType.entries[it], context)
}
} }
} }
} }
} }
observeNullable(viewModel.favoriteStatus) { isFavorite -> observeNullable(viewModel.favoriteStatus) { isFavorite ->
binding?.resultFavorite?.isVisible = isFavorite != null
binding?.resultFavoriteButton?.apply { binding?.resultFavoriteButton?.apply {
isVisible = isFavorite != null
if (isFavorite == null) return@observeNullable if (isFavorite == null) return@observeNullable
val drawable = if (isFavorite) { val drawable = if (isFavorite) {
@ -552,14 +573,8 @@ class ResultFragmentTv : Fragment() {
R.drawable.ic_baseline_favorite_border_24 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) setIconResource(drawable)
setText(text)
setOnClickListener { setOnClickListener {
viewModel.toggleFavoriteStatus(context) { newStatus: Boolean? -> viewModel.toggleFavoriteStatus(context) { newStatus: Boolean? ->
if (newStatus == null) return@toggleFavoriteStatus 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 -> observeNullable(viewModel.subscribeStatus) { isSubscribed ->
binding?.resultSubscribe?.isVisible = isSubscribed != null && requireContext().isEmulatorSettings()
binding?.resultSubscribeButton?.apply { binding?.resultSubscribeButton?.apply {
isVisible = isSubscribed != null && context.isEmulatorSettings()
if (isSubscribed == null) return@observeNullable if (isSubscribed == null) return@observeNullable
val drawable = if (isSubscribed) { val drawable = if (isSubscribed) {
@ -589,14 +614,8 @@ class ResultFragmentTv : Fragment() {
R.drawable.baseline_notifications_none_24 R.drawable.baseline_notifications_none_24
} }
val text = if (isSubscribed) {
R.string.action_unsubscribe
} else {
R.string.action_subscribe
}
setIconResource(drawable) setIconResource(drawable)
setText(text)
setOnClickListener { setOnClickListener {
viewModel.toggleSubscriptionStatus(context) { newStatus: Boolean? -> viewModel.toggleSubscriptionStatus(context) { newStatus: Boolean? ->
if (newStatus == null) return@toggleSubscriptionStatus if (newStatus == null) return@toggleSubscriptionStatus
@ -614,32 +633,47 @@ class ResultFragmentTv : Fragment() {
CommonActivity.showToast(txt(message, name), Toast.LENGTH_SHORT) 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 -> observeNullable(viewModel.movie) { data ->
if (data == null) return@observeNullable
binding?.apply { binding?.apply {
resultPlayMovie.isVisible = data is Resource.Success resultPlayMovie.isVisible = (data is Resource.Success) && !comingSoon
resultPlaySeries.isVisible = data == null resultPlaySeries.isVisible = false
seriesHolder.isVisible = data == null resultEpisodesShow.isVisible = false
resultEpisodesShow.isVisible = data == null
(data as? Resource.Success)?.value?.let { (text, ep) -> (data as? Resource.Success)?.value?.let { (text, ep) ->
resultPlayMovie.setText(text) //resultPlayMovieText.setText(text)
resultPlayMovie.setOnClickListener { resultPlayMovieButton.setOnClickListener {
viewModel.handleAction( viewModel.handleAction(
EpisodeClickEvent(ACTION_CLICK_DEFAULT, ep) EpisodeClickEvent(ACTION_CLICK_DEFAULT, ep)
) )
} }
resultPlayMovie.setOnLongClickListener { resultPlayMovieButton.setOnLongClickListener {
viewModel.handleAction( viewModel.handleAction(
EpisodeClickEvent(ACTION_SHOW_OPTIONS, ep) EpisodeClickEvent(ACTION_SHOW_OPTIONS, ep)
) )
return@setOnLongClickListener true return@setOnLongClickListener true
} }
focusPlayButton() //focusPlayButton()
resultPlayMovieButton.requestFocus()
// Stops last button right focus
resultSearchButton.nextFocusRightId = R.id.result_search_Button
} }
} }
//focusPlayButton()
} }
observeNullable(viewModel.selectPopup) { popup -> observeNullable(viewModel.selectPopup) { popup ->
@ -736,19 +770,26 @@ class ResultFragmentTv : Fragment() {
// Used to request focus the first time the episodes are loaded. // Used to request focus the first time the episodes are loaded.
var hasLoadedEpisodesOnce = false var hasLoadedEpisodesOnce = false
observeNullable(viewModel.episodes) { episodes -> observeNullable(viewModel.episodes) { episodes ->
if (episodes == null) return@observeNullable
binding?.apply { 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 // resultEpisodeLoading.isVisible = episodes is Resource.Loading
if (episodes is Resource.Success) { if (episodes is Resource.Success) {
val first = episodes.value.firstOrNull() val first = episodes.value.firstOrNull()
if (first != null) { if (first != null) {
resultPlaySeries.text = context?.getNameFull( resultPlaySeriesText.text = //"${getString(R.string.season_short)}${first.season}:${getString(R.string.episode_short)}${first.episode}"
null, // resume.result.name, we don't want episode title when {
first.episode, first.season != null ->
first.season "${getString(R.string.season_short)}${first.season}:${getString(R.string.episode_short)}${first.episode}"
) else -> "${getString(R.string.episode)} ${first.episode}"
}
resultPlaySeries.setOnClickListener { resultPlaySeriesButton.setOnClickListener {
viewModel.handleAction( viewModel.handleAction(
EpisodeClickEvent( EpisodeClickEvent(
ACTION_CLICK_DEFAULT, ACTION_CLICK_DEFAULT,
@ -756,7 +797,7 @@ class ResultFragmentTv : Fragment() {
) )
) )
} }
resultPlaySeries.setOnLongClickListener { resultPlaySeriesButton.setOnLongClickListener {
viewModel.handleAction( viewModel.handleAction(
EpisodeClickEvent(ACTION_SHOW_OPTIONS, first) EpisodeClickEvent(ACTION_SHOW_OPTIONS, first)
) )
@ -765,6 +806,7 @@ class ResultFragmentTv : Fragment() {
if (!hasLoadedEpisodesOnce) { if (!hasLoadedEpisodesOnce) {
hasLoadedEpisodesOnce = true hasLoadedEpisodesOnce = true
focusPlayButton() focusPlayButton()
resultPlaySeries.requestFocus()
} }
} }
@ -826,6 +868,7 @@ class ResultFragmentTv : Fragment() {
resultMetaYear.setText(d.yearText) resultMetaYear.setText(d.yearText)
resultMetaDuration.setText(d.durationText) resultMetaDuration.setText(d.durationText)
resultMetaRating.setText(d.ratingText) resultMetaRating.setText(d.ratingText)
resultMetaStatus.setText(d.onGoingText)
resultMetaContentRating.setText(d.contentRatingText) resultMetaContentRating.setText(d.contentRatingText)
resultCastText.setText(d.actorsText) resultCastText.setText(d.actorsText)
resultNextAiring.setText(d.nextAiringEpisode) resultNextAiring.setText(d.nextAiringEpisode)
@ -859,8 +902,12 @@ class ResultFragmentTv : Fragment() {
radius = 0, radius = 0,
errorImageDrawable = error 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 resultDataHolder.isGone = d.comingSoon
UIHelper.populateChips(resultTag, d.tags) UIHelper.populateChips(resultTag, d.tags)
resultCastItems.isGone = d.actors.isNullOrEmpty() resultCastItems.isGone = d.actors.isNullOrEmpty()
(resultCastItems.adapter as? ActorAdaptor)?.updateList( (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 // If there is no rating to display, we don't want an empty gap
resultMetaContentRating.width = 0 resultMetaContentRating.width = 0
} }
resultSearchButton.setOnClickListener {
QuickSearchFragment.pushSearch(activity, d.title)
}
} }
is Resource.Loading -> { 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.getId
import com.lagradost.cloudstream3.APIHolder.unixTime import com.lagradost.cloudstream3.APIHolder.unixTime
import com.lagradost.cloudstream3.APIHolder.unixTimeMS import com.lagradost.cloudstream3.APIHolder.unixTimeMS
import com.lagradost.cloudstream3.AcraApplication.Companion.context
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
import com.lagradost.cloudstream3.CommonActivity.activity import com.lagradost.cloudstream3.CommonActivity.activity
import com.lagradost.cloudstream3.CommonActivity.getCastSession 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.metaproviders.SyncRedirector
import com.lagradost.cloudstream3.mvvm.* import com.lagradost.cloudstream3.mvvm.*
import com.lagradost.cloudstream3.syncproviders.AccountManager 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.SyncAPI
import com.lagradost.cloudstream3.syncproviders.providers.Kitsu import com.lagradost.cloudstream3.syncproviders.providers.Kitsu
import com.lagradost.cloudstream3.syncproviders.providers.SimklApi import com.lagradost.cloudstream3.syncproviders.providers.SimklApi
@ -261,8 +263,7 @@ fun LoadResponse.toResultData(repo: APIRepository): ResultData {
metaText = metaText =
if (repo.providerType == ProviderType.MetaProvider) txt(R.string.provider_info_meta) else null, if (repo.providerType == ProviderType.MetaProvider) txt(R.string.provider_info_meta) else null,
durationText = if (dur == null || dur <= 0) null else txt( durationText = if (dur == null || dur <= 0) null else txt(
R.string.duration_format, secondsToReadable(dur * 60, "0 mins")
dur
), ),
onGoingText = if (this is EpisodeResponse) { onGoingText = if (this is EpisodeResponse) {
txt( txt(
@ -2464,7 +2465,7 @@ class ResultViewModel2 : ViewModel() {
ResumeProgress( ResumeProgress(
progress = (viewPos.position / 1000).toInt(), progress = (viewPos.position / 1000).toInt(),
maxProgress = (viewPos.duration / 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

@ -11,6 +11,7 @@ import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser
import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent
@ -261,7 +262,12 @@ class SettingsAccount : PreferenceFragmentCompat() {
setPreferencesFromResource(R.xml.settings_account, rootKey) setPreferencesFromResource(R.xml.settings_account, rootKey)
getPref(R.string.biometric_key)?.setOnPreferenceClickListener { getPref(R.string.biometric_key)?.setOnPreferenceClickListener {
val authEnabled = PreferenceManager.getDefaultSharedPreferences(
context ?: return@setOnPreferenceClickListener false
)
.getBoolean(getString(R.string.biometric_key), false)
if (authEnabled) {
BackupUtils.backup(activity) BackupUtils.backup(activity)
val title = activity?.getString(R.string.biometric_setting) val title = activity?.getString(R.string.biometric_setting)
val warning = activity?.getString(R.string.biometric_warning) val warning = activity?.getString(R.string.biometric_warning)
@ -269,7 +275,7 @@ class SettingsAccount : PreferenceFragmentCompat() {
title as String, title as String,
warning.html() warning.html()
) { onDialogDismissedEvent } ) { onDialogDismissedEvent }
}
true true
} }

View file

@ -65,13 +65,16 @@ object BackupUtils {
PLUGINS_KEY_LOCAL, PLUGINS_KEY_LOCAL,
OPEN_SUBTITLES_USER_KEY, OPEN_SUBTITLES_USER_KEY,
"nginx_user", // Nginx user key
"biometric_key" // can lock down users if backup is shared on a incompatible device DOWNLOAD_EPISODE_CACHE,
"biometric_key", // can lock down users if backup is shared on a incompatible device
"nginx_user" // Nginx user key
) )
/** false if blacklisted key */ /** false if key should not be contained in backup */
private fun String.isTransferable(): Boolean { private fun String.isTransferable(): Boolean {
return !nonTransferableKeys.contains(this) return !nonTransferableKeys.any { this.contains(it) }
} }
private var restoreFileSelector: ActivityResultLauncher<Array<String>>? = null private var restoreFileSelector: ActivityResultLauncher<Array<String>>? = null

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"> <item android:state_focused="true">
<shape android:shape="rectangle"> <shape android:shape="rectangle">
<solid android:color="?attr/white" /> <solid android:color="?attr/white" />
<corners android:radius="3dp"/> <corners android:radius="@dimen/rounded_image_radius"/>
</shape> </shape>
</item> </item>
<item> <item>
<shape android:shape="rectangle"> <shape android:shape="rectangle">
<solid android:color="@color/white_attr_20" /> <solid android:color="@color/white_attr_20" />
<corners android:radius="3dp"/> <corners android:radius="@dimen/rounded_image_radius"/>
</shape> </shape>
</item> </item>
</selector> </selector>

View file

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

View file

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

View file

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

View file

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

View file

@ -78,6 +78,30 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
</LinearLayout> </LinearLayout>
</com.facebook.shimmer.ShimmerFrameLayout> </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 <LinearLayout
android:id="@+id/result_loading_error" android:id="@+id/result_loading_error"
@ -124,31 +148,6 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:textColor="?attr/textColor" /> android:textColor="?attr/textColor" />
</LinearLayout> </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 <androidx.core.widget.NestedScrollView
android:id="@+id/result_finish_loading" android:id="@+id/result_finish_loading"
android:layout_width="match_parent" 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_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:layout_marginTop="175dp"> android:layout_marginTop="225dp">
<TextView <TextView
android:id="@+id/result_title" android:id="@+id/result_title"
@ -175,7 +174,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:gravity="center_vertical" android:gravity="center_vertical"
android:singleLine="true" android:singleLine="true"
android:textColor="?attr/textColor" android:textColor="?attr/textColor"
android:textSize="20sp" android:textSize="25sp"
android:textStyle="bold" android:textStyle="bold"
tools:text="The Perfect Run The Perfect Run" /> 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" android:textStyle="normal"
tools:text="5d 3h 30m" /> tools:text="5d 3h 30m" />
</LinearLayout> </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>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:layout_marginTop="10dp"> android:layout_marginTop="10dp"
android:baselineAligned="false">
<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>
<LinearLayout <LinearLayout
android:id="@+id/right_layout" 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_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/linearLayout2" app:layout_constraintStart_toEndOf="@+id/linearLayout2"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent"
tools:ignore="UselessParent">
<com.lagradost.cloudstream3.widget.FlowLayout <com.lagradost.cloudstream3.widget.FlowLayout
android:layout_width="match_parent" 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:foreground="@drawable/outline_drawable"
android:maxLines="7" android:maxLines="7"
android:focusable="true" android:focusable="true"
android:nextFocusUp="@id/result_back" android:nextFocusUp="@id/result_play_parent"
android:nextFocusDown="@id/result_bookmark_button" android:nextFocusDown="@id/result_cast_items"
android:padding="5dp" android:padding="5dp"
android:requiresFadingEdge="vertical" android:requiresFadingEdge="vertical"
android:textColor="?attr/textColor" android:textColor="?attr/textColor"
@ -450,59 +582,8 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
<com.google.android.material.chip.ChipGroup <com.google.android.material.chip.ChipGroup
android:id="@+id/result_tag" android:id="@+id/result_tag"
style="@style/ChipParent" style="@style/ChipParent"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> 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>
</LinearLayout> </LinearLayout>
@ -513,10 +594,8 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:descendantFocusability="afterDescendants" android:descendantFocusability="afterDescendants"
android:fadingEdge="horizontal" android:fadingEdge="horizontal"
android:focusable="false" android:nextFocusUp="@id/result_description"
android:focusableInTouchMode="false" android:nextFocusDown="@id/result_recommendations_list"
android:nextFocusUp="@id/result_episodes_show"
android:nextFocusDown="@id/result_recommendations_filter_selection"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingTop="5dp" android:paddingTop="5dp"
android:requiresFadingEdge="horizontal" android:requiresFadingEdge="horizontal"
@ -525,8 +604,23 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
tools:listitem="@layout/cast_item" tools:listitem="@layout/cast_item"
tools:visibility="visible" /> 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 <LinearLayout
android:id="@+id/result_recommendations_holder" android:id="@+id/result_recommendations_holder"
android:descendantFocusability="afterDescendants"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
@ -540,7 +634,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:nextFocusUp="@id/result_cast_items" android:nextFocusUp="@id/result_cast_items"
android:nextFocusDown="@id/result_recommendations_list" android:nextFocusDown="@id/result_recommendations_list"
android:descendantFocusability="afterDescendants"
android:orientation="horizontal" android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="2" tools:itemCount="2"
@ -563,7 +657,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clipToPadding="false" android:clipToPadding="false"
android:descendantFocusability="afterDescendants" android:descendantFocusability="afterDescendants"
android:nextFocusUp="@id/result_recommendations_filter_selection" android:nextFocusUp="@id/result_cast_items"
android:orientation="vertical" android:orientation="vertical"
app:spanCount="8" app:spanCount="8"
tools:listitem="@layout/search_result_grid" /> 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_height="match_parent"
android:layout_gravity="end" android:layout_gravity="end"
android:visibility="gone" 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_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> 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 <androidx.cardview.widget.CardView
android:id="@+id/result_poster_holder" android:id="@+id/result_poster_holder"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -1067,70 +1016,47 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
android:visibility="gone" android:visibility="gone"
app:icon="@drawable/ic_baseline_add_24" /> app:icon="@drawable/ic_baseline_add_24" />
</LinearLayout>
<!--<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_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:layout_gravity="start"
android:animateLayoutChanges="true"
android:orientation="vertical"
tools:visibility="visible">
<ImageView <LinearLayout
android:id="@+id/result_resume_series_button" android:id="@+id/series_holder"
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"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:orientation="vertical">
android:gravity="center"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:textColor="?attr/textColor"
android:textSize="17sp"
android:textStyle="bold"
tools:text="S1E1 Episode 1" />
<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>
</LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</FrameLayout> </FrameLayout>

View file

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

View file

@ -69,6 +69,7 @@
<string name="enable_skip_op_from_database" translatable="false">enable_skip_op_from_database</string> <string name="enable_skip_op_from_database" translatable="false">enable_skip_op_from_database</string>
<string name="rotate_video_key" translatable="false">rotate_video_key</string> <string name="rotate_video_key" translatable="false">rotate_video_key</string>
<string name="auto_rotate_video_key" translatable="false">auto_rotate_video_key</string> <string name="auto_rotate_video_key" translatable="false">auto_rotate_video_key</string>
<string name="biometric_key" translatable="false">biometric_key</string>
<!-- FORMAT MIGHT TRANSLATE, WILL CAUSE CRASH IF APPLIED WRONG --> <!-- FORMAT MIGHT TRANSLATE, WILL CAUSE CRASH IF APPLIED WRONG -->
<string name="extra_info_format" formatted="true" translatable="false">%d %s | %s</string> <string name="extra_info_format" formatted="true" translatable="false">%d %s | %s</string>
<string name="storage_size_format" formatted="true" translatable="false">%s • %s</string> <string name="storage_size_format" formatted="true" translatable="false">%s • %s</string>
@ -306,6 +307,7 @@
<string name="go_forward_30">+30</string> <string name="go_forward_30">+30</string>
<string name="delete_message" formatted="true">This will permanently delete %s\nAre you sure?</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_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_ongoing">Ongoing</string>
<string name="status_completed">Completed</string> <string name="status_completed">Completed</string>
<string name="status">Status</string> <string name="status">Status</string>
@ -756,17 +758,17 @@
<string name="rotate_video_desc">Display a toggle button for screen orientation</string> <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_desc">Enable automatic switching of screen orientation based on video orientation</string>
<string name="auto_rotate_video">Auto rotate</string> <string name="auto_rotate_video">Auto rotate</string>
<string name="favorite">Favorite</string>
<string name="unfavorite">Unfavorite</string>
<!-- For Biometrics --> <!-- For Biometrics -->
<string name="biometric_authentication_title">Unlock CloudStream</string> <string name="biometric_authentication_title">Unlock CloudStream</string>
<string name="biometric_setting">Lock with Biometrics</string> <string name="biometric_setting">Lock with Biometrics</string>
<string name="biometric_key" translatable="false">biometric_key</string>
<string name="password_pin_authentication_title">Password/PIN Authentication</string> <string name="password_pin_authentication_title">Password/PIN Authentication</string>
<string name="biometric_unsupported">Biometric authentication is not supported on this device</string> <string name="biometric_unsupported">Biometric authentication is not supported on this device</string>
<string name="phone_not_secured">Please disable fingerprint authentication if device has no lock.</string>
<string name="biometric_setting_summary">Unlock the app with Fingerprint, Face ID, PIN, Pattern and Password.</string> <string name="biometric_setting_summary">Unlock the app with Fingerprint, Face ID, PIN, Pattern and Password.</string>
<string name="biometric_prompt_description">This window will close after few failed attempts. You\'ll have to restart the App.</string> <string name="biometric_prompt_description">This window will close after few failed attempts. You\'ll have to restart the App.</string>
<string name="biometric_warning">Your CloudStream data has been backed up now, although probability of this rare case is very low but all <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, 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> Clear the app data wholly and restore the backup. Any inconvenience if arrived is deeply regretted.</string>
</resources> </resources>

View file

@ -814,6 +814,35 @@
<item name="android:insetTop">0dp</item> <item name="android:insetTop">0dp</item>
</style> </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"> <style name="VideoButtonTV">
<item name="android:tag">@string/tv_no_focus_tag</item> <item name="android:tag">@string/tv_no_focus_tag</item>
<item name="android:stateListAnimator">@null</item> <item name="android:stateListAnimator">@null</item>