mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Merge branch 'recloudstream:master' into master
This commit is contained in:
commit
05dd490ab7
14 changed files with 188 additions and 45 deletions
|
@ -58,8 +58,8 @@ android {
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 33
|
targetSdk = 33
|
||||||
|
|
||||||
versionCode = 60
|
versionCode = 62
|
||||||
versionName = "4.1.9"
|
versionName = "4.2.0"
|
||||||
|
|
||||||
resValue("string", "app_version", "${defaultConfig.versionName}${versionNameSuffix ?: ""}")
|
resValue("string", "app_version", "${defaultConfig.versionName}${versionNameSuffix ?: ""}")
|
||||||
resValue("string", "commit_hash", "git rev-parse --short HEAD".execute() ?: "")
|
resValue("string", "commit_hash", "git rev-parse --short HEAD".execute() ?: "")
|
||||||
|
|
|
@ -497,6 +497,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
R.id.navigation_results_phone,
|
R.id.navigation_results_phone,
|
||||||
R.id.navigation_results_tv,
|
R.id.navigation_results_tv,
|
||||||
R.id.navigation_player,
|
R.id.navigation_player,
|
||||||
|
R.id.navigation_quick_search,
|
||||||
).contains(destination.id)
|
).contains(destination.id)
|
||||||
|
|
||||||
binding?.navHostFragment?.apply {
|
binding?.navHostFragment?.apply {
|
||||||
|
@ -1101,15 +1102,19 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
updateTv()
|
updateTv()
|
||||||
|
|
||||||
// backup when we update the app, I don't trust myself to not boot lock users, might want to make this a setting?
|
// backup when we update the app, I don't trust myself to not boot lock users, might want to make this a setting?
|
||||||
try {
|
normalSafeApiCall {
|
||||||
val appVer = BuildConfig.VERSION_NAME
|
val appVer = BuildConfig.VERSION_NAME
|
||||||
val lastAppAutoBackup: String = getKey("VERSION_NAME") ?: ""
|
val lastAppAutoBackup: String = getKey("VERSION_NAME") ?: ""
|
||||||
if (appVer != lastAppAutoBackup) {
|
if (appVer != lastAppAutoBackup) {
|
||||||
setKey("VERSION_NAME", BuildConfig.VERSION_NAME)
|
setKey("VERSION_NAME", BuildConfig.VERSION_NAME)
|
||||||
backup()
|
normalSafeApiCall {
|
||||||
|
backup()
|
||||||
|
}
|
||||||
|
normalSafeApiCall {
|
||||||
|
// Recompile oat on new version
|
||||||
|
PluginManager.deleteAllOatFiles(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (t: Throwable) {
|
|
||||||
logError(t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// just in case, MAIN SHOULD *NEVER* BOOT LOOP CRASH
|
// just in case, MAIN SHOULD *NEVER* BOOT LOOP CRASH
|
||||||
|
|
|
@ -137,6 +137,20 @@ object PluginManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all generated oat files which will force Android to recompile the dex extensions.
|
||||||
|
* This might fix unrecoverable SIGSEGV exceptions when old oat files are loaded in a new app update.
|
||||||
|
*/
|
||||||
|
fun deleteAllOatFiles(context: Context) {
|
||||||
|
File("${context.filesDir}/${ONLINE_PLUGINS_FOLDER}").listFiles()?.forEach { repo ->
|
||||||
|
repo.listFiles { file -> file.name == "oat" && file.isDirectory }?.forEach { file ->
|
||||||
|
val success = file.deleteRecursively()
|
||||||
|
Log.i(TAG, "Deleted oat directory: ${file.absolutePath} Success=$success")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getPluginsOnline(): Array<PluginData> {
|
fun getPluginsOnline(): Array<PluginData> {
|
||||||
return getKey(PLUGINS_KEY) ?: emptyArray()
|
return getKey(PLUGINS_KEY) ?: emptyArray()
|
||||||
}
|
}
|
||||||
|
|
|
@ -461,6 +461,11 @@ class HomeParentItemAdapterPreview(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
homePreviewSearchButton.setOnClickListener { _ ->
|
||||||
|
// Open blank screen.
|
||||||
|
viewModel.queryTextSubmit("")
|
||||||
|
}
|
||||||
|
|
||||||
// This makes the hidden next buttons only available when on the info button
|
// This makes the hidden next buttons only available when on the info button
|
||||||
// Otherwise you might be able to go to the next item without being at the info button
|
// Otherwise you might be able to go to the next item without being at the info button
|
||||||
homePreviewInfoBtt.setOnFocusChangeListener { _, hasFocus ->
|
homePreviewInfoBtt.setOnFocusChangeListener { _, hasFocus ->
|
||||||
|
|
|
@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.launchSafe
|
import com.lagradost.cloudstream3.mvvm.launchSafe
|
||||||
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||||
import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
||||||
|
@ -15,6 +16,7 @@ import com.lagradost.cloudstream3.utils.EpisodeSkip
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorUri
|
import com.lagradost.cloudstream3.utils.ExtractorUri
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class PlayerGeneratorViewModel : ViewModel() {
|
class PlayerGeneratorViewModel : ViewModel() {
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -38,6 +40,11 @@ class PlayerGeneratorViewModel : ViewModel() {
|
||||||
private val _currentSubtitleYear = MutableLiveData<Int?>(null)
|
private val _currentSubtitleYear = MutableLiveData<Int?>(null)
|
||||||
val currentSubtitleYear: LiveData<Int?> = _currentSubtitleYear
|
val currentSubtitleYear: LiveData<Int?> = _currentSubtitleYear
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the Episode ID to prevent starting multiple link loading Jobs when preloading links.
|
||||||
|
*/
|
||||||
|
private var currentLoadingEpisodeId: Int? = null
|
||||||
|
|
||||||
fun setSubtitleYear(year: Int?) {
|
fun setSubtitleYear(year: Int?) {
|
||||||
_currentSubtitleYear.postValue(year)
|
_currentSubtitleYear.postValue(year)
|
||||||
}
|
}
|
||||||
|
@ -72,18 +79,32 @@ class PlayerGeneratorViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun preLoadNextLinks() {
|
fun preLoadNextLinks() {
|
||||||
|
val id = getId()
|
||||||
|
// Do not preload if already loading
|
||||||
|
if (id == currentLoadingEpisodeId) return
|
||||||
|
|
||||||
Log.i(TAG, "preLoadNextLinks")
|
Log.i(TAG, "preLoadNextLinks")
|
||||||
currentJob?.cancel()
|
currentJob?.cancel()
|
||||||
currentJob = viewModelScope.launchSafe {
|
currentLoadingEpisodeId = id
|
||||||
if (generator?.hasCache == true && generator?.hasNext() == true) {
|
|
||||||
safeApiCall {
|
currentJob = viewModelScope.launch {
|
||||||
generator?.generateLinks(
|
try {
|
||||||
type = LoadType.InApp,
|
if (generator?.hasCache == true && generator?.hasNext() == true) {
|
||||||
clearCache = false,
|
safeApiCall {
|
||||||
callback = {},
|
generator?.generateLinks(
|
||||||
subtitleCallback = {},
|
type = LoadType.InApp,
|
||||||
offset = 1
|
clearCache = false,
|
||||||
)
|
callback = {},
|
||||||
|
subtitleCallback = {},
|
||||||
|
offset = 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
logError(t)
|
||||||
|
} finally {
|
||||||
|
if (currentLoadingEpisodeId == id) {
|
||||||
|
currentLoadingEpisodeId = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,14 +183,14 @@ class PlayerGeneratorViewModel : ViewModel() {
|
||||||
// load more data
|
// load more data
|
||||||
_loadingLinks.postValue(Resource.Loading())
|
_loadingLinks.postValue(Resource.Loading())
|
||||||
val loadingState = safeApiCall {
|
val loadingState = safeApiCall {
|
||||||
generator?.generateLinks(type = type,clearCache = clearCache, callback = {
|
generator?.generateLinks(type = type, clearCache = clearCache, callback = {
|
||||||
currentLinks.add(it)
|
currentLinks.add(it)
|
||||||
// Clone to prevent ConcurrentModificationException
|
// Clone to prevent ConcurrentModificationException
|
||||||
normalSafeApiCall {
|
normalSafeApiCall {
|
||||||
// Extra normalSafeApiCall since .toSet() iterates.
|
// Extra normalSafeApiCall since .toSet() iterates.
|
||||||
_currentLinks.postValue(currentLinks.toSet())
|
_currentLinks.postValue(currentLinks.toSet())
|
||||||
}
|
}
|
||||||
}, subtitleCallback = {
|
}, subtitleCallback = {
|
||||||
currentSubs.add(it)
|
currentSubs.add(it)
|
||||||
normalSafeApiCall {
|
normalSafeApiCall {
|
||||||
_currentSubs.postValue(currentSubs.toSet())
|
_currentSubs.postValue(currentSubs.toSet())
|
||||||
|
|
|
@ -33,6 +33,7 @@ import com.lagradost.cloudstream3.ui.search.SearchAdapter
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
|
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchHelper
|
import com.lagradost.cloudstream3.ui.search.SearchHelper
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchViewModel
|
import com.lagradost.cloudstream3.ui.search.SearchViewModel
|
||||||
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.ownShow
|
import com.lagradost.cloudstream3.utils.AppUtils.ownShow
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper
|
import com.lagradost.cloudstream3.utils.UIHelper
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
|
@ -269,6 +270,10 @@ class QuickSearchFragment : Fragment() {
|
||||||
activity?.popCurrentPage()
|
activity?.popCurrentPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isTrueTvSettings()) {
|
||||||
|
binding?.quickSearch?.requestFocus()
|
||||||
|
}
|
||||||
|
|
||||||
arguments?.getString(AUTOSEARCH_KEY)?.let {
|
arguments?.getString(AUTOSEARCH_KEY)?.let {
|
||||||
binding?.quickSearch?.setQuery(it, true)
|
binding?.quickSearch?.setQuery(it, true)
|
||||||
arguments?.remove(AUTOSEARCH_KEY)
|
arguments?.remove(AUTOSEARCH_KEY)
|
||||||
|
|
|
@ -3,6 +3,8 @@ package com.lagradost.cloudstream3.ui.result
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.annotation.IdRes
|
||||||
|
import androidx.annotation.LayoutRes
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
@ -12,7 +14,10 @@ import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.databinding.CastItemBinding
|
import com.lagradost.cloudstream3.databinding.CastItemBinding
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||||
|
|
||||||
class ActorAdaptor(private val focusCallback : (View?) -> Unit = {}) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
class ActorAdaptor(
|
||||||
|
private var nextFocusUpId: Int? = null,
|
||||||
|
private val focusCallback: (View?) -> Unit = {}
|
||||||
|
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
data class ActorMetaData(
|
data class ActorMetaData(
|
||||||
var isInverted: Boolean,
|
var isInverted: Boolean,
|
||||||
val actor: ActorData,
|
val actor: ActorData,
|
||||||
|
@ -22,7 +27,8 @@ class ActorAdaptor(private val focusCallback : (View?) -> Unit = {}) : RecyclerV
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
return CardViewHolder(
|
return CardViewHolder(
|
||||||
CastItemBinding.inflate(LayoutInflater.from(parent.context), parent, false), focusCallback
|
CastItemBinding.inflate(LayoutInflater.from(parent.context), parent, false),
|
||||||
|
focusCallback
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,10 +70,10 @@ class ActorAdaptor(private val focusCallback : (View?) -> Unit = {}) : RecyclerV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CardViewHolder
|
private inner class CardViewHolder
|
||||||
constructor(
|
constructor(
|
||||||
val binding: CastItemBinding,
|
val binding: CastItemBinding,
|
||||||
private val focusCallback : (View?) -> Unit = {}
|
private val focusCallback: (View?) -> Unit = {}
|
||||||
) :
|
) :
|
||||||
RecyclerView.ViewHolder(binding.root) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
@ -78,8 +84,18 @@ class ActorAdaptor(private val focusCallback : (View?) -> Unit = {}) : RecyclerV
|
||||||
Pair(actor.voiceActor?.image, actor.actor.image)
|
Pair(actor.voiceActor?.image, actor.actor.image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix tv focus escaping the recyclerview
|
||||||
|
if (position == 0) {
|
||||||
|
itemView.nextFocusLeftId = R.id.result_cast_items
|
||||||
|
} else if ((position - 1) == itemCount) {
|
||||||
|
itemView.nextFocusRightId = R.id.result_cast_items
|
||||||
|
}
|
||||||
|
nextFocusUpId?.let {
|
||||||
|
itemView.nextFocusUpId = it
|
||||||
|
}
|
||||||
|
|
||||||
itemView.setOnFocusChangeListener { v, hasFocus ->
|
itemView.setOnFocusChangeListener { v, hasFocus ->
|
||||||
if(hasFocus) {
|
if (hasFocus) {
|
||||||
focusCallback(v)
|
focusCallback(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,10 +114,20 @@ class ResultFragmentTv : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasNoFocus(): Boolean {
|
// private fun hasNoFocus(): Boolean {
|
||||||
val focus = activity?.currentFocus
|
// val focus = activity?.currentFocus
|
||||||
if (focus == null || !focus.isVisible) return true
|
// if (focus == null || !focus.isVisible) return true
|
||||||
return focus == binding?.resultRoot
|
// return focus == binding?.resultRoot
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force focus any play button.
|
||||||
|
* 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()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setRecommendations(rec: List<SearchResponse>?, validApiName: String?) {
|
private fun setRecommendations(rec: List<SearchResponse>?, validApiName: String?) {
|
||||||
|
@ -413,7 +423,13 @@ class ResultFragmentTv : Fragment() {
|
||||||
setHorizontal()
|
setHorizontal()
|
||||||
}
|
}
|
||||||
|
|
||||||
resultCastItems.adapter = ActorAdaptor {
|
val aboveCast = listOf(
|
||||||
|
binding?.resultEpisodesShow,
|
||||||
|
binding?.resultBookmarkButton,
|
||||||
|
).firstOrNull {
|
||||||
|
it?.isVisible == true
|
||||||
|
}
|
||||||
|
resultCastItems.adapter = ActorAdaptor(aboveCast?.id) {
|
||||||
toggleEpisodes(false)
|
toggleEpisodes(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -454,9 +470,7 @@ class ResultFragmentTv : Fragment() {
|
||||||
resultPlaySeries.isVisible = false
|
resultPlaySeries.isVisible = false
|
||||||
resultResumeSeries.isVisible = true
|
resultResumeSeries.isVisible = true
|
||||||
|
|
||||||
if (hasNoFocus()) {
|
focusPlayButton()
|
||||||
resultResumeSeries.requestFocus()
|
|
||||||
}
|
|
||||||
|
|
||||||
resultResumeSeries.text =
|
resultResumeSeries.text =
|
||||||
if (resume.isMovie) context?.getString(R.string.play_movie_button) else context?.getNameFull(
|
if (resume.isMovie) context?.getString(R.string.play_movie_button) else context?.getNameFull(
|
||||||
|
@ -539,9 +553,7 @@ class ResultFragmentTv : Fragment() {
|
||||||
)
|
)
|
||||||
return@setOnLongClickListener true
|
return@setOnLongClickListener true
|
||||||
}
|
}
|
||||||
if (hasNoFocus()) {
|
focusPlayButton()
|
||||||
resultPlayMovie.requestFocus()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -636,6 +648,9 @@ class ResultFragmentTv : Fragment() {
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used to request focus the first time the episodes are loaded.
|
||||||
|
var hasLoadedEpisodesOnce = false
|
||||||
observeNullable(viewModel.episodes) { episodes ->
|
observeNullable(viewModel.episodes) { episodes ->
|
||||||
binding?.apply {
|
binding?.apply {
|
||||||
resultEpisodes.isVisible = episodes is Resource.Success
|
resultEpisodes.isVisible = episodes is Resource.Success
|
||||||
|
@ -663,6 +678,10 @@ class ResultFragmentTv : Fragment() {
|
||||||
)
|
)
|
||||||
return@setOnLongClickListener true
|
return@setOnLongClickListener true
|
||||||
}
|
}
|
||||||
|
if (!hasLoadedEpisodesOnce) {
|
||||||
|
hasLoadedEpisodesOnce = true
|
||||||
|
focusPlayButton()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -205,6 +205,11 @@ class SettingsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default focus on TV
|
||||||
|
if (isTrueTv) {
|
||||||
|
settingsGeneral.requestFocus()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -109,18 +109,19 @@ class InAppUpdater {
|
||||||
releases.sortedWith(compareBy {
|
releases.sortedWith(compareBy {
|
||||||
versionRegex.find(it.name)?.groupValues?.get(2)
|
versionRegex.find(it.name)?.groupValues?.get(2)
|
||||||
}).toList().lastOrNull()*/
|
}).toList().lastOrNull()*/
|
||||||
val found =
|
val foundList =
|
||||||
response.filter { rel ->
|
response.filter { rel ->
|
||||||
!rel.prerelease
|
!rel.prerelease
|
||||||
}.sortedWith(compareBy { release ->
|
}.sortedWith(compareBy { release ->
|
||||||
release.assets.filter { it.content_type == "application/vnd.android.package-archive" }
|
release.assets.firstOrNull { it.content_type == "application/vnd.android.package-archive" }?.name?.let { it1 ->
|
||||||
.getOrNull(0)?.name?.let { it1 ->
|
|
||||||
versionRegex.find(
|
versionRegex.find(
|
||||||
it1
|
it1
|
||||||
)?.groupValues?.get(2)
|
)?.groupValues?.let {
|
||||||
|
it[3].toInt() * 100_000_000 + it[4].toInt() * 10_000 + it[5].toInt()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}).toList().lastOrNull()
|
}).toList()
|
||||||
|
val found = foundList.lastOrNull()
|
||||||
val foundAsset = found?.assets?.getOrNull(0)
|
val foundAsset = found?.assets?.getOrNull(0)
|
||||||
val currentVersion = packageName?.let {
|
val currentVersion = packageName?.let {
|
||||||
packageManager.getPackageInfo(
|
packageManager.getPackageInfo(
|
||||||
|
|
|
@ -114,6 +114,22 @@
|
||||||
android:nextFocusRight="@id/home_switch_account"
|
android:nextFocusRight="@id/home_switch_account"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/home_preview_search_button"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:background="@drawable/player_button_tv_attr_no_bg"
|
||||||
|
android:contentDescription="@string/search"
|
||||||
|
android:nextFocusLeft="@id/home_change_api"
|
||||||
|
android:nextFocusRight="@id/home_preview_switch_account"
|
||||||
|
android:nextFocusDown="@id/home_preview_info_btt"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:src="@drawable/search_icon"
|
||||||
|
android:tag="@string/tv_no_focus_tag"
|
||||||
|
app:tint="@color/player_on_button_tv_attr" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/home_switch_account"
|
android:id="@+id/home_switch_account"
|
||||||
|
|
||||||
|
|
|
@ -45,9 +45,24 @@
|
||||||
android:background="@drawable/player_button_tv_attr_no_bg"
|
android:background="@drawable/player_button_tv_attr_no_bg"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:nextFocusLeft="@id/nav_rail_view"
|
android:nextFocusLeft="@id/nav_rail_view"
|
||||||
android:nextFocusRight="@id/home_preview_switch_account"
|
android:nextFocusRight="@id/home_preview_search_button"
|
||||||
android:nextFocusDown="@id/home_preview_play_btt" />
|
android:nextFocusDown="@id/home_preview_play_btt" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/home_preview_search_button"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:background="@drawable/player_button_tv_attr_no_bg"
|
||||||
|
android:contentDescription="@string/search"
|
||||||
|
android:nextFocusLeft="@id/home_preview_change_api"
|
||||||
|
android:nextFocusRight="@id/home_preview_switch_account"
|
||||||
|
android:nextFocusDown="@id/home_preview_info_btt"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:src="@drawable/search_icon"
|
||||||
|
android:tag="@string/tv_no_focus_tag"
|
||||||
|
app:tint="@color/player_on_button_tv_attr" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/home_preview_switch_account"
|
android:id="@+id/home_preview_switch_account"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -55,7 +70,8 @@
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
android:background="@drawable/player_button_tv_attr_no_bg"
|
android:background="@drawable/player_button_tv_attr_no_bg"
|
||||||
android:contentDescription="@string/account"
|
android:contentDescription="@string/account"
|
||||||
android:nextFocusLeft="@id/home_preview_change_api"
|
android:nextFocusLeft="@id/home_preview_search_button"
|
||||||
|
android:nextFocusRight="@id/home_preview_switch_account"
|
||||||
android:nextFocusDown="@id/home_preview_info_btt"
|
android:nextFocusDown="@id/home_preview_info_btt"
|
||||||
|
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
|
|
|
@ -113,7 +113,25 @@
|
||||||
android:background="@drawable/player_button_tv_attr_no_bg"
|
android:background="@drawable/player_button_tv_attr_no_bg"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:nextFocusLeft="@id/nav_rail_view"
|
android:nextFocusLeft="@id/nav_rail_view"
|
||||||
android:nextFocusRight="@id/home_switch_account" />
|
android:nextFocusRight="@id/home_preview_search_button"
|
||||||
|
android:nextFocusDown="@id/home_preview_play_btt" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/home_preview_search_button"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:background="@drawable/player_button_tv_attr_no_bg"
|
||||||
|
android:clickable="true"
|
||||||
|
android:contentDescription="@string/search"
|
||||||
|
android:focusable="true"
|
||||||
|
android:nextFocusLeft="@id/home_change_api"
|
||||||
|
android:nextFocusRight="@id/home_switch_account"
|
||||||
|
android:nextFocusDown="@id/home_preview_info_btt"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:src="@drawable/search_icon"
|
||||||
|
android:tag="@string/tv_no_focus_tag"
|
||||||
|
app:tint="@color/player_on_button_tv_attr" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/home_switch_account"
|
android:id="@+id/home_switch_account"
|
||||||
|
@ -122,7 +140,9 @@
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
android:background="@drawable/player_button_tv_attr_no_bg"
|
android:background="@drawable/player_button_tv_attr_no_bg"
|
||||||
android:contentDescription="@string/account"
|
android:contentDescription="@string/account"
|
||||||
android:nextFocusLeft="@id/home_change_api"
|
android:nextFocusLeft="@id/home_preview_search_button"
|
||||||
|
android:nextFocusRight="@id/home_switch_account"
|
||||||
|
android:nextFocusDown="@id/home_change_api"
|
||||||
|
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
android:src="@drawable/ic_outline_account_circle_24"
|
android:src="@drawable/ic_outline_account_circle_24"
|
||||||
|
|
|
@ -99,7 +99,7 @@
|
||||||
android:id="@+id/search_autofit_results"
|
android:id="@+id/search_autofit_results"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="@dimen/navbar_width"
|
||||||
android:background="?attr/primaryBlackBackground"
|
android:background="?attr/primaryBlackBackground"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:descendantFocusability="afterDescendants"
|
android:descendantFocusability="afterDescendants"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue