mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
tv focus changes + gradle bump + pip crash fix
This commit is contained in:
parent
653982a6bd
commit
f5c4864a3c
28 changed files with 590 additions and 320 deletions
|
@ -1,4 +1,3 @@
|
||||||
import com.android.build.gradle.api.BaseVariantOutput
|
|
||||||
import org.jetbrains.dokka.gradle.DokkaTask
|
import org.jetbrains.dokka.gradle.DokkaTask
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
@ -52,7 +51,7 @@ android {
|
||||||
targetSdk = 33
|
targetSdk = 33
|
||||||
|
|
||||||
versionCode = 59
|
versionCode = 59
|
||||||
versionName = "4.1.1"
|
versionName = "4.1.2"
|
||||||
|
|
||||||
resValue("string", "app_version", "${defaultConfig.versionName}${versionNameSuffix ?: ""}")
|
resValue("string", "app_version", "${defaultConfig.versionName}${versionNameSuffix ?: ""}")
|
||||||
|
|
||||||
|
@ -108,14 +107,19 @@ android {
|
||||||
versionCode = (System.currentTimeMillis() / 60000).toInt()
|
versionCode = (System.currentTimeMillis() / 60000).toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//toolchain {
|
||||||
|
// languageVersion.set(JavaLanguageVersion.of(17))
|
||||||
|
// }
|
||||||
|
// jvmToolchain(17)
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
isCoreLibraryDesugaringEnabled = true
|
isCoreLibraryDesugaringEnabled = true
|
||||||
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "17"
|
||||||
freeCompilerArgs = listOf("-Xjvm-default=compatibility")
|
freeCompilerArgs = listOf("-Xjvm-default=compatibility")
|
||||||
}
|
}
|
||||||
lint {
|
lint {
|
||||||
|
@ -131,22 +135,22 @@ repositories {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.google.android.mediahome:video:1.0.0")
|
implementation("com.google.android.mediahome:video:1.0.0")
|
||||||
implementation("androidx.test.ext:junit-ktx:1.1.3")
|
implementation("androidx.test.ext:junit-ktx:1.1.5")
|
||||||
testImplementation("org.json:json:20180813")
|
testImplementation("org.json:json:20180813")
|
||||||
|
|
||||||
implementation("androidx.core:core-ktx:1.8.0")
|
implementation("androidx.core:core-ktx:1.10.1")
|
||||||
implementation("androidx.appcompat:appcompat:1.4.2") // need target 32 for 1.5.0
|
implementation("androidx.appcompat:appcompat:1.6.1") // need target 32 for 1.5.0
|
||||||
|
|
||||||
// dont change this to 1.6.0 it looks ugly af
|
// dont change this to 1.6.0 it looks ugly af
|
||||||
implementation("com.google.android.material:material:1.5.0")
|
implementation("com.google.android.material:material:1.5.0")
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
implementation("androidx.navigation:navigation-fragment-ktx:2.5.1")
|
implementation("androidx.navigation:navigation-fragment-ktx:2.6.0")
|
||||||
implementation("androidx.navigation:navigation-ui-ktx:2.5.1")
|
implementation("androidx.navigation:navigation-ui-ktx:2.6.0")
|
||||||
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.5.1")
|
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.1")
|
||||||
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1")
|
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
|
||||||
testImplementation("junit:junit:4.13.2")
|
testImplementation("junit:junit:4.13.2")
|
||||||
androidTestImplementation("androidx.test.ext:junit:1.1.3")
|
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
|
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||||
androidTestImplementation("androidx.test:core")
|
androidTestImplementation("androidx.test:core")
|
||||||
|
|
||||||
//implementation("io.karn:khttp-android:0.1.2") //okhttp instead
|
//implementation("io.karn:khttp-android:0.1.2") //okhttp instead
|
||||||
|
@ -201,8 +205,8 @@ dependencies {
|
||||||
//implementation("com.github.TorrentStream:TorrentStream-Android:2.7.0")
|
//implementation("com.github.TorrentStream:TorrentStream-Android:2.7.0")
|
||||||
|
|
||||||
// Downloading
|
// Downloading
|
||||||
implementation("androidx.work:work-runtime:2.8.0")
|
implementation("androidx.work:work-runtime:2.8.1")
|
||||||
implementation("androidx.work:work-runtime-ktx:2.8.0")
|
implementation("androidx.work:work-runtime-ktx:2.8.1")
|
||||||
|
|
||||||
// Networking
|
// Networking
|
||||||
// implementation("com.squareup.okhttp3:okhttp:4.9.2")
|
// implementation("com.squareup.okhttp3:okhttp:4.9.2")
|
||||||
|
|
|
@ -19,8 +19,11 @@ import androidx.annotation.StringRes
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.children
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.google.android.gms.cast.framework.CastSession
|
import com.google.android.gms.cast.framework.CastSession
|
||||||
|
import com.google.android.material.chip.ChipGroup
|
||||||
|
import com.google.android.material.navigationrail.NavigationRailView
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
|
@ -39,6 +42,13 @@ import org.schabi.newpipe.extractor.NewPipe
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
enum class FocusDirection {
|
||||||
|
Start,
|
||||||
|
End,
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
}
|
||||||
|
|
||||||
object CommonActivity {
|
object CommonActivity {
|
||||||
|
|
||||||
private var _activity: WeakReference<Activity>? = null
|
private var _activity: WeakReference<Activity>? = null
|
||||||
|
@ -318,17 +328,70 @@ object CommonActivity {
|
||||||
currentLook = currentLook.parent as? View ?: break
|
currentLook = currentLook.parent as? View ?: break
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/** skips the initial stage of searching for an id using the view, see getNextFocus for specification */
|
||||||
|
fun continueGetNextFocus(
|
||||||
|
root: Any?,
|
||||||
|
view: View,
|
||||||
|
direction: FocusDirection,
|
||||||
|
nextId: Int,
|
||||||
|
depth: Int = 0
|
||||||
|
): View? {
|
||||||
|
if (nextId == NO_ID) return null
|
||||||
|
|
||||||
|
// do an initial search for the view, in case the localLook is too deep we can use this as
|
||||||
|
// an early break and backup view
|
||||||
|
var next =
|
||||||
|
when (root) {
|
||||||
|
is Activity -> root.findViewById(nextId)
|
||||||
|
is View -> root.rootView.findViewById<View?>(nextId)
|
||||||
|
else -> null
|
||||||
|
} ?: return null
|
||||||
|
|
||||||
|
next = localLook(view, nextId) ?: next
|
||||||
|
|
||||||
|
// if cant focus but visible then break and let android decide
|
||||||
|
// the exception if is the view is a parent and has children that wants focus
|
||||||
|
val hasChildrenThatWantsFocus = (next as? ViewGroup)?.let { parent ->
|
||||||
|
parent.descendantFocusability == ViewGroup.FOCUS_AFTER_DESCENDANTS && parent.childCount > 0
|
||||||
|
} ?: false
|
||||||
|
if (!next.isFocusable && next.isShown && !hasChildrenThatWantsFocus) return null
|
||||||
|
|
||||||
|
// if not shown then continue because we will "skip" over views to get to a replacement
|
||||||
|
if (!next.isShown) {
|
||||||
|
// we don't want a while true loop, so we let android decide if we find a recursive view
|
||||||
|
if (next == view) return null
|
||||||
|
return getNextFocus(root, next, direction, depth + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
(when (next) {
|
||||||
|
is ChipGroup -> {
|
||||||
|
next.children.firstOrNull { it.isFocusable && it.isShown }
|
||||||
|
}
|
||||||
|
|
||||||
|
is NavigationRailView -> {
|
||||||
|
next.findViewById(next.selectedItemId) ?: next.findViewById(R.id.navigation_home)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> null
|
||||||
|
})?.let {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
|
// nothing wrong with the view found, return it
|
||||||
|
return next
|
||||||
|
}
|
||||||
|
|
||||||
/** recursively looks for a next focus up to a depth of 10,
|
/** recursively looks for a next focus up to a depth of 10,
|
||||||
* this is used to override the normal shit focus system
|
* this is used to override the normal shit focus system
|
||||||
* because this application has a lot of invisible views that messes with some tv devices*/
|
* because this application has a lot of invisible views that messes with some tv devices*/
|
||||||
private fun getNextFocus(
|
fun getNextFocus(
|
||||||
act: Activity?,
|
root: Any?,
|
||||||
view: View?,
|
view: View?,
|
||||||
direction: FocusDirection,
|
direction: FocusDirection,
|
||||||
depth: Int = 0
|
depth: Int = 0
|
||||||
): View? {
|
): View? {
|
||||||
// if input is invalid let android decide + depth test to not crash if loop is found
|
// if input is invalid let android decide + depth test to not crash if loop is found
|
||||||
if (view == null || depth >= 10 || act == null) {
|
if (view == null || depth >= 10 || root == null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,31 +426,9 @@ object CommonActivity {
|
||||||
if (nextId == NO_ID)
|
if (nextId == NO_ID)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
return continueGetNextFocus(root, view, direction, nextId, depth)
|
||||||
var next = act.findViewById<View?>(nextId) ?: return null
|
|
||||||
|
|
||||||
next = localLook(view, nextId) ?: next
|
|
||||||
|
|
||||||
// if cant focus but visible then break and let android decide
|
|
||||||
// the exception if is the view is a parent and has children that wants focus
|
|
||||||
val hasChildrenThatWantsFocus = (next as? ViewGroup)?.let { parent ->
|
|
||||||
parent.descendantFocusability == ViewGroup.FOCUS_AFTER_DESCENDANTS && parent.childCount > 0
|
|
||||||
} ?: false
|
|
||||||
if (!next.isFocusable && next.isShown && !hasChildrenThatWantsFocus) return null
|
|
||||||
|
|
||||||
// if not shown then continue because we will "skip" over views to get to a replacement
|
|
||||||
if (!next.isShown) return getNextFocus(act, next, direction, depth + 1)
|
|
||||||
|
|
||||||
// nothing wrong with the view found, return it
|
|
||||||
return next
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum class FocusDirection {
|
|
||||||
Start,
|
|
||||||
End,
|
|
||||||
Up,
|
|
||||||
Down,
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onKeyDown(act: Activity?, keyCode: Int, event: KeyEvent?) {
|
fun onKeyDown(act: Activity?, keyCode: Int, event: KeyEvent?) {
|
||||||
//println("Keycode: $keyCode")
|
//println("Keycode: $keyCode")
|
||||||
|
|
|
@ -5,11 +5,12 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.databinding.FragmentChildDownloadsBinding
|
import com.lagradost.cloudstream3.databinding.FragmentChildDownloadsBinding
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
||||||
|
import com.lagradost.cloudstream3.ui.result.FOCUS_SELF
|
||||||
|
import com.lagradost.cloudstream3.ui.result.setLinearListLayout
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
||||||
|
@ -110,7 +111,11 @@ class DownloadChildFragment : Fragment() {
|
||||||
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it }
|
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it }
|
||||||
|
|
||||||
binding?.downloadChildList?.adapter = adapter
|
binding?.downloadChildList?.adapter = adapter
|
||||||
binding?.downloadChildList?.layoutManager = GridLayoutManager(context, 1)
|
binding?.downloadChildList?.setLinearListLayout(
|
||||||
|
isHorizontal = false,
|
||||||
|
nextDown = FOCUS_SELF,
|
||||||
|
nextRight = FOCUS_SELF
|
||||||
|
)//layoutManager = GridLayoutManager(context, 1)
|
||||||
|
|
||||||
updateList(folder)
|
updateList(folder)
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,8 @@ import com.lagradost.cloudstream3.databinding.FragmentDownloadsBinding
|
||||||
import com.lagradost.cloudstream3.databinding.StreamInputBinding
|
import com.lagradost.cloudstream3.databinding.StreamInputBinding
|
||||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.ui.player.BasicLink
|
import com.lagradost.cloudstream3.ui.player.BasicLink
|
||||||
|
import com.lagradost.cloudstream3.ui.result.FOCUS_SELF
|
||||||
|
import com.lagradost.cloudstream3.ui.result.setLinearListLayout
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
||||||
|
@ -74,7 +76,7 @@ class DownloadFragment : Fragment() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
var binding : FragmentDownloadsBinding? = null
|
var binding: FragmentDownloadsBinding? = null
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
|
@ -151,6 +153,7 @@ class DownloadFragment : Fragment() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
1 -> {
|
1 -> {
|
||||||
(activity as AppCompatActivity?)?.loadResult(
|
(activity as AppCompatActivity?)?.loadResult(
|
||||||
click.data.url,
|
click.data.url,
|
||||||
|
@ -187,7 +190,13 @@ class DownloadFragment : Fragment() {
|
||||||
|
|
||||||
binding?.downloadList?.apply {
|
binding?.downloadList?.apply {
|
||||||
this.adapter = adapter
|
this.adapter = adapter
|
||||||
layoutManager = GridLayoutManager(context, 1)
|
setLinearListLayout(
|
||||||
|
isHorizontal = false,
|
||||||
|
nextRight = FOCUS_SELF,
|
||||||
|
nextUp = FOCUS_SELF,
|
||||||
|
nextDown = FOCUS_SELF
|
||||||
|
)
|
||||||
|
//layoutManager = GridLayoutManager(context, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should be visible in emulator layout
|
// Should be visible in emulator layout
|
||||||
|
|
|
@ -88,14 +88,14 @@ class HomeChildItemAdapter(
|
||||||
private val nextFocusUp: Int? = null,
|
private val nextFocusUp: Int? = null,
|
||||||
private val nextFocusDown: Int? = null,
|
private val nextFocusDown: Int? = null,
|
||||||
private val isHorizontal: Boolean = false,
|
private val isHorizontal: Boolean = false,
|
||||||
private val isRtl : Boolean
|
private val isRtl: Boolean
|
||||||
) :
|
) :
|
||||||
RecyclerView.ViewHolder(binding.root) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
fun bind(card: SearchResponse, position: Int) {
|
fun bind(card: SearchResponse, position: Int) {
|
||||||
|
|
||||||
// TV focus fixing
|
// TV focus fixing
|
||||||
val nextFocusBehavior = when (position) {
|
/*val nextFocusBehavior = when (position) {
|
||||||
0 -> true
|
0 -> true
|
||||||
itemCount - 1 -> false
|
itemCount - 1 -> false
|
||||||
else -> null
|
else -> null
|
||||||
|
@ -113,7 +113,7 @@ class HomeChildItemAdapter(
|
||||||
} else {
|
} else {
|
||||||
itemView.nextFocusRightId = -1
|
itemView.nextFocusRightId = -1
|
||||||
itemView.nextFocusLeftId = -1
|
itemView.nextFocusLeftId = -1
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
||||||
when (binding) {
|
when (binding) {
|
||||||
|
@ -171,7 +171,7 @@ class HomeChildItemAdapter(
|
||||||
card,
|
card,
|
||||||
position,
|
position,
|
||||||
itemView,
|
itemView,
|
||||||
nextFocusBehavior,
|
null, // nextFocusBehavior,
|
||||||
nextFocusUp,
|
nextFocusUp,
|
||||||
nextFocusDown
|
nextFocusDown
|
||||||
)
|
)
|
||||||
|
|
|
@ -310,6 +310,17 @@ class HomeFragment : Fragment() {
|
||||||
selectedTypes: List<TvType>,
|
selectedTypes: List<TvType>,
|
||||||
validTypes: List<TvType>,
|
validTypes: List<TvType>,
|
||||||
callback: (List<TvType>) -> Unit
|
callback: (List<TvType>) -> Unit
|
||||||
|
) {
|
||||||
|
bindChips(header, selectedTypes, validTypes, callback, null, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bindChips(
|
||||||
|
header: TvtypesChipsBinding?,
|
||||||
|
selectedTypes: List<TvType>,
|
||||||
|
validTypes: List<TvType>,
|
||||||
|
callback: (List<TvType>) -> Unit,
|
||||||
|
nextFocusDown: Int?,
|
||||||
|
nextFocusUp: Int?
|
||||||
) {
|
) {
|
||||||
if (header == null) return
|
if (header == null) return
|
||||||
val pairList = getPairList(header)
|
val pairList = getPairList(header)
|
||||||
|
@ -317,6 +328,17 @@ class HomeFragment : Fragment() {
|
||||||
val isValid = validTypes.any { types.contains(it) }
|
val isValid = validTypes.any { types.contains(it) }
|
||||||
button?.isVisible = isValid
|
button?.isVisible = isValid
|
||||||
button?.isChecked = isValid && selectedTypes.any { types.contains(it) }
|
button?.isChecked = isValid && selectedTypes.any { types.contains(it) }
|
||||||
|
button?.isFocusable = true
|
||||||
|
if (isTrueTvSettings()) {
|
||||||
|
button?.isFocusableInTouchMode = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextFocusDown != null)
|
||||||
|
button?.nextFocusDownId = nextFocusDown
|
||||||
|
|
||||||
|
if (nextFocusUp != null)
|
||||||
|
button?.nextFocusUpId = nextFocusUp
|
||||||
|
|
||||||
button?.setOnCheckedChangeListener { _, _ ->
|
button?.setOnCheckedChangeListener { _, _ ->
|
||||||
val list = ArrayList<TvType>()
|
val list = ArrayList<TvType>()
|
||||||
for ((sbutton, vvalidTypes) in pairList) {
|
for ((sbutton, vvalidTypes) in pairList) {
|
||||||
|
@ -462,7 +484,7 @@ class HomeFragment : Fragment() {
|
||||||
|
|
||||||
private val apiChangeClickListener = View.OnClickListener { view ->
|
private val apiChangeClickListener = View.OnClickListener { view ->
|
||||||
view.context.selectHomepage(currentApiName) { api ->
|
view.context.selectHomepage(currentApiName) { api ->
|
||||||
homeViewModel.loadAndCancel(api, forceReload = true,fromUI = true)
|
homeViewModel.loadAndCancel(api, forceReload = true, fromUI = true)
|
||||||
}
|
}
|
||||||
/*val validAPIs = view.context?.filterProviderByPreferredMedia()?.toMutableList() ?: mutableListOf()
|
/*val validAPIs = view.context?.filterProviderByPreferredMedia()?.toMutableList() ?: mutableListOf()
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import com.lagradost.cloudstream3.HomePageList
|
||||||
import com.lagradost.cloudstream3.LoadResponse
|
import com.lagradost.cloudstream3.LoadResponse
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.databinding.HomepageParentBinding
|
import com.lagradost.cloudstream3.databinding.HomepageParentBinding
|
||||||
|
import com.lagradost.cloudstream3.ui.result.FOCUS_SELF
|
||||||
import com.lagradost.cloudstream3.ui.result.setLinearListLayout
|
import com.lagradost.cloudstream3.ui.result.setLinearListLayout
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
|
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchFragment.Companion.filterSearchResponse
|
import com.lagradost.cloudstream3.ui.search.SearchFragment.Companion.filterSearchResponse
|
||||||
|
@ -162,7 +163,8 @@ open class ParentItemAdapter(
|
||||||
RecyclerView.ViewHolder(binding.root) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
val title: TextView = binding.homeChildMoreInfo
|
val title: TextView = binding.homeChildMoreInfo
|
||||||
private val recyclerView: RecyclerView = binding.homeChildRecyclerview
|
private val recyclerView: RecyclerView = binding.homeChildRecyclerview
|
||||||
|
private val startFocus = R.id.nav_rail_view
|
||||||
|
private val endFocus = FOCUS_SELF
|
||||||
fun update(expand: HomeViewModel.ExpandableHomepageList) {
|
fun update(expand: HomeViewModel.ExpandableHomepageList) {
|
||||||
val info = expand.list
|
val info = expand.list
|
||||||
(recyclerView.adapter as? HomeChildItemAdapter?)?.apply {
|
(recyclerView.adapter as? HomeChildItemAdapter?)?.apply {
|
||||||
|
@ -176,8 +178,13 @@ open class ParentItemAdapter(
|
||||||
nextFocusDown = recyclerView.nextFocusDownId,
|
nextFocusDown = recyclerView.nextFocusDownId,
|
||||||
).apply {
|
).apply {
|
||||||
isHorizontal = info.isHorizontalImages
|
isHorizontal = info.isHorizontalImages
|
||||||
|
hasNext = expand.hasNext
|
||||||
}
|
}
|
||||||
recyclerView.setLinearListLayout()
|
recyclerView.setLinearListLayout(
|
||||||
|
isHorizontal = true,
|
||||||
|
nextLeft = startFocus,
|
||||||
|
nextRight = endFocus,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +199,11 @@ open class ParentItemAdapter(
|
||||||
isHorizontal = info.isHorizontalImages
|
isHorizontal = info.isHorizontalImages
|
||||||
hasNext = expand.hasNext
|
hasNext = expand.hasNext
|
||||||
}
|
}
|
||||||
recyclerView.setLinearListLayout()
|
recyclerView.setLinearListLayout(
|
||||||
|
isHorizontal = true,
|
||||||
|
nextLeft = startFocus,
|
||||||
|
nextRight = endFocus,
|
||||||
|
)
|
||||||
title.text = info.name
|
title.text = info.name
|
||||||
|
|
||||||
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import com.lagradost.cloudstream3.mvvm.debugException
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
import com.lagradost.cloudstream3.ui.WatchType
|
||||||
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.selectHomepage
|
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.selectHomepage
|
||||||
|
import com.lagradost.cloudstream3.ui.result.FOCUS_SELF
|
||||||
import com.lagradost.cloudstream3.ui.result.ResultViewModel2
|
import com.lagradost.cloudstream3.ui.result.ResultViewModel2
|
||||||
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
|
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
|
||||||
import com.lagradost.cloudstream3.ui.result.setLinearListLayout
|
import com.lagradost.cloudstream3.ui.result.setLinearListLayout
|
||||||
|
@ -439,8 +440,8 @@ class HomeParentItemAdapterPreview(
|
||||||
resumeRecyclerView.adapter = resumeAdapter
|
resumeRecyclerView.adapter = resumeAdapter
|
||||||
bookmarkRecyclerView.adapter = bookmarkAdapter
|
bookmarkRecyclerView.adapter = bookmarkAdapter
|
||||||
|
|
||||||
resumeRecyclerView.setLinearListLayout()
|
resumeRecyclerView.setLinearListLayout(nextLeft = R.id.nav_rail_view, nextRight = FOCUS_SELF)
|
||||||
bookmarkRecyclerView.setLinearListLayout()
|
bookmarkRecyclerView.setLinearListLayout(nextLeft = R.id.nav_rail_view, nextRight = FOCUS_SELF)
|
||||||
|
|
||||||
fixPaddingStatusbarMargin(topPadding)
|
fixPaddingStatusbarMargin(topPadding)
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import android.util.Rational
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class PlayerPipHelper {
|
class PlayerPipHelper {
|
||||||
|
@ -88,10 +89,12 @@ class PlayerPipHelper {
|
||||||
val ratioAccuracy = 100000 // To convert the float to int
|
val ratioAccuracy = 100000 // To convert the float to int
|
||||||
|
|
||||||
// java.lang.IllegalArgumentException: setPictureInPictureParams: Aspect ratio is too extreme (must be between 0.418410 and 2.390000)
|
// java.lang.IllegalArgumentException: setPictureInPictureParams: Aspect ratio is too extreme (must be between 0.418410 and 2.390000)
|
||||||
val fixedRational = aspectRatio?.toFloat()?.coerceIn(mixAspectRatio, maxAspectRatio)?.let {
|
val fixedRational =
|
||||||
|
aspectRatio?.toFloat()?.coerceIn(mixAspectRatio, maxAspectRatio)?.let {
|
||||||
Rational((it * ratioAccuracy).roundToInt(), ratioAccuracy)
|
Rational((it * ratioAccuracy).roundToInt(), ratioAccuracy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
normalSafeApiCall {
|
||||||
activity.setPictureInPictureParams(
|
activity.setPictureInPictureParams(
|
||||||
PictureInPictureParams.Builder()
|
PictureInPictureParams.Builder()
|
||||||
.apply {
|
.apply {
|
||||||
|
@ -106,4 +109,5 @@ class PlayerPipHelper {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -4,19 +4,45 @@ import android.content.Context
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.lagradost.cloudstream3.CommonActivity
|
||||||
|
import com.lagradost.cloudstream3.CommonActivity.activity
|
||||||
|
import com.lagradost.cloudstream3.FocusDirection
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
|
|
||||||
fun RecyclerView?.setLinearListLayout(isHorizontal: Boolean = true) {
|
const val FOCUS_SELF = View.NO_ID - 1
|
||||||
if (this == null) return
|
const val FOCUS_INHERIT = FOCUS_SELF - 1
|
||||||
|
|
||||||
|
fun RecyclerView?.setLinearListLayout(
|
||||||
|
isHorizontal: Boolean = true,
|
||||||
|
nextLeft: Int = FOCUS_INHERIT,
|
||||||
|
nextRight: Int = FOCUS_INHERIT,
|
||||||
|
nextUp: Int = FOCUS_INHERIT,
|
||||||
|
nextDown: Int = FOCUS_INHERIT
|
||||||
|
) {
|
||||||
|
if (this == null) return
|
||||||
|
val ctx = this.context ?: return
|
||||||
this.layoutManager =
|
this.layoutManager =
|
||||||
this.context?.let { LinearListLayout(it).apply { if (isHorizontal) setHorizontal() else setVertical() } }
|
LinearListLayout(ctx).apply {
|
||||||
// ?: this.layoutManager
|
if (isHorizontal) setHorizontal() else setVertical()
|
||||||
|
nextFocusLeft =
|
||||||
|
if (nextLeft == FOCUS_INHERIT) this@setLinearListLayout.nextFocusLeftId else nextLeft
|
||||||
|
nextFocusRight =
|
||||||
|
if (nextRight == FOCUS_INHERIT) this@setLinearListLayout.nextFocusRightId else nextRight
|
||||||
|
nextFocusUp =
|
||||||
|
if (nextUp == FOCUS_INHERIT) this@setLinearListLayout.nextFocusUpId else nextUp
|
||||||
|
nextFocusDown =
|
||||||
|
if (nextDown == FOCUS_INHERIT) this@setLinearListLayout.nextFocusDownId else nextDown
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class LinearListLayout(context: Context?) :
|
open class LinearListLayout(context: Context?) :
|
||||||
LinearLayoutManager(context) {
|
LinearLayoutManager(context) {
|
||||||
|
|
||||||
|
var nextFocusLeft: Int = View.NO_ID
|
||||||
|
var nextFocusRight: Int = View.NO_ID
|
||||||
|
var nextFocusUp: Int = View.NO_ID
|
||||||
|
var nextFocusDown: Int = View.NO_ID
|
||||||
|
|
||||||
fun setHorizontal() {
|
fun setHorizontal() {
|
||||||
orientation = HORIZONTAL
|
orientation = HORIZONTAL
|
||||||
}
|
}
|
||||||
|
@ -56,8 +82,37 @@ open class LinearListLayout(context: Context?) :
|
||||||
linearSmoothScroller.targetPosition = position
|
linearSmoothScroller.targetPosition = position
|
||||||
startSmoothScroll(linearSmoothScroller)
|
startSmoothScroll(linearSmoothScroller)
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/** from the current focus go to a direction */
|
||||||
|
private fun getNextDirection(focused: View?, direction: FocusDirection): View? {
|
||||||
|
val id = when (direction) {
|
||||||
|
FocusDirection.Start -> if (isLayoutRTL) nextFocusRight else nextFocusLeft
|
||||||
|
FocusDirection.End -> if (isLayoutRTL) nextFocusLeft else nextFocusRight
|
||||||
|
FocusDirection.Up -> nextFocusUp
|
||||||
|
FocusDirection.Down -> nextFocusDown
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (id) {
|
||||||
|
View.NO_ID -> null
|
||||||
|
FOCUS_SELF -> focused
|
||||||
|
else -> CommonActivity.continueGetNextFocus(
|
||||||
|
activity ?: focused,
|
||||||
|
focused ?: return null,
|
||||||
|
direction,
|
||||||
|
id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onInterceptFocusSearch(focused: View, direction: Int): View? {
|
override fun onInterceptFocusSearch(focused: View, direction: Int): View? {
|
||||||
val dir = if (orientation == HORIZONTAL) {
|
val dir = if (orientation == HORIZONTAL) {
|
||||||
|
if (direction == View.FOCUS_DOWN) getNextDirection(focused, FocusDirection.Down)?.let { newFocus ->
|
||||||
|
return newFocus
|
||||||
|
}
|
||||||
|
if (direction == View.FOCUS_UP) getNextDirection(focused, FocusDirection.Up)?.let { newFocus ->
|
||||||
|
return newFocus
|
||||||
|
}
|
||||||
|
|
||||||
if (direction == View.FOCUS_DOWN || direction == View.FOCUS_UP) {
|
if (direction == View.FOCUS_DOWN || direction == View.FOCUS_UP) {
|
||||||
// This scrolls the recyclerview before doing focus search, which
|
// This scrolls the recyclerview before doing focus search, which
|
||||||
// allows the focus search to work better.
|
// allows the focus search to work better.
|
||||||
|
@ -69,34 +124,45 @@ open class LinearListLayout(context: Context?) :
|
||||||
}
|
}
|
||||||
var ret = if (direction == View.FOCUS_RIGHT) 1 else -1
|
var ret = if (direction == View.FOCUS_RIGHT) 1 else -1
|
||||||
// only flip on horizontal layout
|
// only flip on horizontal layout
|
||||||
if (this.isLayoutRTL) {
|
if (isLayoutRTL) {
|
||||||
ret = -ret
|
ret = -ret
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
} else {
|
} else {
|
||||||
if (direction == View.FOCUS_RIGHT || direction == View.FOCUS_LEFT) return null
|
if (direction == View.FOCUS_RIGHT) getNextDirection(focused, FocusDirection.End)?.let { newFocus ->
|
||||||
|
return newFocus
|
||||||
|
}
|
||||||
|
if (direction == View.FOCUS_LEFT) getNextDirection(focused, FocusDirection.Start)?.let { newFocus ->
|
||||||
|
return newFocus
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction == View.FOCUS_RIGHT || direction == View.FOCUS_LEFT) {
|
||||||
|
(focused.parent as? RecyclerView)?.focusSearch(direction)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (direction == View.FOCUS_RIGHT || direction == View.FOCUS_LEFT) return null
|
||||||
if (direction == View.FOCUS_DOWN) 1 else -1
|
if (direction == View.FOCUS_DOWN) 1 else -1
|
||||||
}
|
}
|
||||||
|
|
||||||
return try {
|
try {
|
||||||
getPosition(getCorrectParent(focused))?.let { position ->
|
val position = getPosition(getCorrectParent(focused)) ?: return null
|
||||||
val lookfor = dir + position
|
val lookFor = dir + position
|
||||||
//clamp(dir + position, 0, recyclerView.adapter?.itemCount ?: return null)
|
|
||||||
|
|
||||||
// refocus on the same view if going out of bounds, note that we only do it
|
// if out of bounds then refocus as specified
|
||||||
// for out of bounds one way as we may override the start where item == -1
|
return if (lookFor >= itemCount) {
|
||||||
if (lookfor >= itemCount) {
|
getNextDirection(focused, if(orientation == HORIZONTAL) FocusDirection.End else FocusDirection.Down)
|
||||||
return getViewFromPos(itemCount - 1) ?: focused
|
} else if (lookFor < 0) {
|
||||||
}
|
getNextDirection(focused, if(orientation == HORIZONTAL) FocusDirection.Start else FocusDirection.Up)
|
||||||
|
} else {
|
||||||
getViewFromPos(lookfor) ?: run {
|
getViewFromPos(lookFor) ?: run {
|
||||||
scrollToPosition(lookfor)
|
scrollToPosition(lookFor)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logError(e)
|
logError(e)
|
||||||
null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -294,7 +294,7 @@ open class ResultFragmentPhone : FullScreenPlayer(),
|
||||||
super.onStop()
|
super.onStop()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateUI(id : Int?) {
|
private fun updateUI(id: Int?) {
|
||||||
syncModel.updateUserData()
|
syncModel.updateUserData()
|
||||||
viewModel.reloadEpisodes()
|
viewModel.reloadEpisodes()
|
||||||
}
|
}
|
||||||
|
@ -338,7 +338,12 @@ open class ResultFragmentPhone : FullScreenPlayer(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
resultCastItems.layoutManager = object : LinearListLayout(view.context) {
|
resultCastItems.setLinearListLayout(
|
||||||
|
isHorizontal = true,
|
||||||
|
nextLeft = FOCUS_SELF,
|
||||||
|
nextRight = FOCUS_SELF
|
||||||
|
)
|
||||||
|
/*resultCastItems.layoutManager = object : LinearListLayout(view.context) {
|
||||||
override fun onRequestChildFocus(
|
override fun onRequestChildFocus(
|
||||||
parent: RecyclerView,
|
parent: RecyclerView,
|
||||||
state: RecyclerView.State,
|
state: RecyclerView.State,
|
||||||
|
@ -356,7 +361,7 @@ open class ResultFragmentPhone : FullScreenPlayer(),
|
||||||
}
|
}
|
||||||
}.apply {
|
}.apply {
|
||||||
this.orientation = RecyclerView.HORIZONTAL
|
this.orientation = RecyclerView.HORIZONTAL
|
||||||
}
|
}*/
|
||||||
resultCastItems.adapter = ActorAdaptor()
|
resultCastItems.adapter = ActorAdaptor()
|
||||||
|
|
||||||
resultEpisodes.adapter =
|
resultEpisodes.adapter =
|
||||||
|
@ -597,8 +602,14 @@ open class ResultFragmentPhone : FullScreenPlayer(),
|
||||||
EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, ep)
|
EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, ep)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
DOWNLOAD_ACTION_LONG_CLICK -> {
|
DOWNLOAD_ACTION_LONG_CLICK -> {
|
||||||
viewModel.handleAction(EpisodeClickEvent(ACTION_DOWNLOAD_MIRROR, ep))
|
viewModel.handleAction(
|
||||||
|
EpisodeClickEvent(
|
||||||
|
ACTION_DOWNLOAD_MIRROR,
|
||||||
|
ep
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> DownloadButtonSetup.handleDownloadClick(click)
|
else -> DownloadButtonSetup.handleDownloadClick(click)
|
||||||
|
|
|
@ -307,7 +307,29 @@ class ResultFragmentTv : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resultEpisodes.setLinearListLayout(isHorizontal = false)/*.layoutManager =
|
resultEpisodes.setLinearListLayout(
|
||||||
|
isHorizontal = false,
|
||||||
|
nextUp = FOCUS_SELF,
|
||||||
|
nextDown = FOCUS_SELF,
|
||||||
|
nextRight = FOCUS_SELF,
|
||||||
|
)
|
||||||
|
resultDubSelection.setLinearListLayout(
|
||||||
|
isHorizontal = false,
|
||||||
|
nextUp = FOCUS_SELF,
|
||||||
|
nextDown = FOCUS_SELF,
|
||||||
|
)
|
||||||
|
resultRangeSelection.setLinearListLayout(
|
||||||
|
isHorizontal = false,
|
||||||
|
nextUp = FOCUS_SELF,
|
||||||
|
nextDown = FOCUS_SELF,
|
||||||
|
)
|
||||||
|
resultSeasonSelection.setLinearListLayout(
|
||||||
|
isHorizontal = false,
|
||||||
|
nextUp = FOCUS_SELF,
|
||||||
|
nextDown = FOCUS_SELF,
|
||||||
|
)
|
||||||
|
|
||||||
|
/*.layoutManager =
|
||||||
LinearListLayout(resultEpisodes.context, resultEpisodes.isRtl()).apply {
|
LinearListLayout(resultEpisodes.context, resultEpisodes.isRtl()).apply {
|
||||||
setVertical()
|
setVertical()
|
||||||
}*/
|
}*/
|
||||||
|
@ -367,6 +389,11 @@ class ResultFragmentTv : Fragment() {
|
||||||
)
|
)
|
||||||
|
|
||||||
resultCastItems.layoutManager = object : LinearListLayout(view.context) {
|
resultCastItems.layoutManager = object : LinearListLayout(view.context) {
|
||||||
|
|
||||||
|
override fun onInterceptFocusSearch(focused: View, direction: Int): View? {
|
||||||
|
return super.onInterceptFocusSearch(focused, direction)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onRequestChildFocus(
|
override fun onRequestChildFocus(
|
||||||
parent: RecyclerView,
|
parent: RecyclerView,
|
||||||
state: RecyclerView.State,
|
state: RecyclerView.State,
|
||||||
|
@ -383,8 +410,9 @@ class ResultFragmentTv : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.apply {
|
}.apply {
|
||||||
this.orientation = RecyclerView.HORIZONTAL
|
setHorizontal()
|
||||||
}
|
}
|
||||||
|
|
||||||
resultCastItems.adapter = ActorAdaptor {
|
resultCastItems.adapter = ActorAdaptor {
|
||||||
toggleEpisodes(false)
|
toggleEpisodes(false)
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,8 @@ import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.currentSpan
|
||||||
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.loadHomepageList
|
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.loadHomepageList
|
||||||
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.updateChips
|
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.updateChips
|
||||||
import com.lagradost.cloudstream3.ui.home.ParentItemAdapter
|
import com.lagradost.cloudstream3.ui.home.ParentItemAdapter
|
||||||
|
import com.lagradost.cloudstream3.ui.result.FOCUS_SELF
|
||||||
|
import com.lagradost.cloudstream3.ui.result.setLinearListLayout
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.ownHide
|
import com.lagradost.cloudstream3.utils.AppUtils.ownHide
|
||||||
|
@ -519,9 +521,12 @@ class SearchFragment : Fragment() {
|
||||||
|
|
||||||
binding?.apply {
|
binding?.apply {
|
||||||
searchHistoryRecycler.adapter = historyAdapter
|
searchHistoryRecycler.adapter = historyAdapter
|
||||||
searchHistoryRecycler.layoutManager = GridLayoutManager(context, 1)
|
searchHistoryRecycler.setLinearListLayout(isHorizontal = false, nextRight = FOCUS_SELF)
|
||||||
|
//searchHistoryRecycler.layoutManager = GridLayoutManager(context, 1)
|
||||||
|
|
||||||
searchMasterRecycler.adapter = masterAdapter
|
searchMasterRecycler.adapter = masterAdapter
|
||||||
|
//searchMasterRecycler.setLinearListLayout(isHorizontal = false, nextRight = FOCUS_SELF)
|
||||||
|
|
||||||
searchMasterRecycler.layoutManager = GridLayoutManager(context, 1)
|
searchMasterRecycler.layoutManager = GridLayoutManager(context, 1)
|
||||||
|
|
||||||
// Automatically search the specified query, this allows the app search to launch from intent
|
// Automatically search the specified query, this allows the app search to launch from intent
|
||||||
|
|
|
@ -23,6 +23,8 @@ import com.lagradost.cloudstream3.databinding.FragmentExtensionsBinding
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import com.lagradost.cloudstream3.mvvm.observeNullable
|
import com.lagradost.cloudstream3.mvvm.observeNullable
|
||||||
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
||||||
|
import com.lagradost.cloudstream3.ui.result.FOCUS_SELF
|
||||||
|
import com.lagradost.cloudstream3.ui.result.setLinearListLayout
|
||||||
import com.lagradost.cloudstream3.ui.result.setText
|
import com.lagradost.cloudstream3.ui.result.setText
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar
|
||||||
|
@ -82,6 +84,14 @@ class ExtensionsFragment : Fragment() {
|
||||||
|
|
||||||
setUpToolbar(R.string.extensions)
|
setUpToolbar(R.string.extensions)
|
||||||
|
|
||||||
|
binding?.repoRecyclerView?.setLinearListLayout(
|
||||||
|
isHorizontal = false,
|
||||||
|
nextUp = R.id.settings_toolbar, //FOCUS_SELF, // back has no id so we cant :pensive:
|
||||||
|
nextDown = R.id.plugin_storage_appbar,
|
||||||
|
nextRight = FOCUS_SELF,
|
||||||
|
nextLeft = R.id.nav_rail_view
|
||||||
|
)
|
||||||
|
|
||||||
binding?.repoRecyclerView?.adapter = RepoAdapter(false, {
|
binding?.repoRecyclerView?.adapter = RepoAdapter(false, {
|
||||||
findNavController().navigate(
|
findNavController().navigate(
|
||||||
R.id.navigation_settings_extensions_to_navigation_settings_plugins,
|
R.id.navigation_settings_extensions_to_navigation_settings_plugins,
|
||||||
|
@ -126,11 +136,11 @@ class ExtensionsFragment : Fragment() {
|
||||||
(binding?.repoRecyclerView?.adapter as? RepoAdapter)?.updateList(it)
|
(binding?.repoRecyclerView?.adapter as? RepoAdapter)?.updateList(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding?.repoRecyclerView?.apply {
|
/*binding?.repoRecyclerView?.apply {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
layoutManager = LinearRecycleViewLayoutManager(ctx, nextFocusUpId, nextFocusDownId)
|
layoutManager = LinearRecycleViewLayoutManager(ctx, nextFocusUpId, nextFocusDownId)
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// list_repositories?.setOnClickListener {
|
// list_repositories?.setOnClickListener {
|
||||||
// // Open webview on tv if browser fails
|
// // Open webview on tv if browser fails
|
||||||
|
|
|
@ -88,7 +88,8 @@ class PluginDetailsFragment(val data: PluginViewData) : BottomSheetDialogFragmen
|
||||||
if (metadata.authors.isEmpty()) getString(R.string.no_data) else metadata.authors.joinToString(
|
if (metadata.authors.isEmpty()) getString(R.string.no_data) else metadata.authors.joinToString(
|
||||||
", "
|
", "
|
||||||
)
|
)
|
||||||
pluginStatus.text = resources.getStringArray(R.array.extension_statuses)[metadata.status]
|
pluginStatus.text =
|
||||||
|
resources.getStringArray(R.array.extension_statuses)[metadata.status]
|
||||||
pluginTypes.text =
|
pluginTypes.text =
|
||||||
if (metadata.tvTypes.isNullOrEmpty()) getString(R.string.no_data) else metadata.tvTypes.joinToString(
|
if (metadata.tvTypes.isNullOrEmpty()) getString(R.string.no_data) else metadata.tvTypes.joinToString(
|
||||||
", "
|
", "
|
||||||
|
|
|
@ -15,6 +15,8 @@ import com.lagradost.cloudstream3.TvType
|
||||||
import com.lagradost.cloudstream3.databinding.FragmentPluginsBinding
|
import com.lagradost.cloudstream3.databinding.FragmentPluginsBinding
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.bindChips
|
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.bindChips
|
||||||
|
import com.lagradost.cloudstream3.ui.result.FOCUS_SELF
|
||||||
|
import com.lagradost.cloudstream3.ui.result.setLinearListLayout
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar
|
||||||
import com.lagradost.cloudstream3.ui.settings.appLanguages
|
import com.lagradost.cloudstream3.ui.settings.appLanguages
|
||||||
|
@ -32,7 +34,7 @@ class PluginsFragment : Fragment() {
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?,
|
savedInstanceState: Bundle?,
|
||||||
): View {
|
): View {
|
||||||
val localBinding = FragmentPluginsBinding.inflate(inflater,container,false)
|
val localBinding = FragmentPluginsBinding.inflate(inflater, container, false)
|
||||||
binding = localBinding
|
binding = localBinding
|
||||||
return localBinding.root//inflater.inflate(R.layout.fragment_plugins, container, false)
|
return localBinding.root//inflater.inflate(R.layout.fragment_plugins, container, false)
|
||||||
}
|
}
|
||||||
|
@ -78,9 +80,11 @@ class PluginsFragment : Fragment() {
|
||||||
R.id.download_all -> {
|
R.id.download_all -> {
|
||||||
PluginsViewModel.downloadAll(activity, url, pluginViewModel)
|
PluginsViewModel.downloadAll(activity, url, pluginViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.lang_filter -> {
|
R.id.lang_filter -> {
|
||||||
val tempLangs = appLanguages.toMutableList()
|
val tempLangs = appLanguages.toMutableList()
|
||||||
val languageCodes = mutableListOf("none") + tempLangs.map { (_, _, iso) -> iso }
|
val languageCodes =
|
||||||
|
mutableListOf("none") + tempLangs.map { (_, _, iso) -> iso }
|
||||||
val languageNames =
|
val languageNames =
|
||||||
mutableListOf(getString(R.string.no_data)) + tempLangs.map { (emoji, name, iso) ->
|
mutableListOf(getString(R.string.no_data)) + tempLangs.map { (emoji, name, iso) ->
|
||||||
val flag =
|
val flag =
|
||||||
|
@ -88,17 +92,18 @@ class PluginsFragment : Fragment() {
|
||||||
"$flag $name"
|
"$flag $name"
|
||||||
}
|
}
|
||||||
val selectedList =
|
val selectedList =
|
||||||
pluginViewModel.languages.map { it -> languageCodes.indexOf(it) }
|
pluginViewModel.languages.map { languageCodes.indexOf(it) }
|
||||||
|
|
||||||
activity?.showMultiDialog(
|
activity?.showMultiDialog(
|
||||||
languageNames,
|
languageNames,
|
||||||
selectedList,
|
selectedList,
|
||||||
getString(R.string.provider_lang_settings),
|
getString(R.string.provider_lang_settings),
|
||||||
{}) { newList ->
|
{}) { newList ->
|
||||||
pluginViewModel.languages = newList.map { it -> languageCodes[it] }
|
pluginViewModel.languages = newList.map { languageCodes[it] }
|
||||||
pluginViewModel.updateFilteredPlugins()
|
pluginViewModel.updateFilteredPlugins()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
return@setOnMenuItemClickListener true
|
return@setOnMenuItemClickListener true
|
||||||
|
@ -137,7 +142,11 @@ class PluginsFragment : Fragment() {
|
||||||
|
|
||||||
// Because onActionViewCollapsed doesn't wanna work we need this workaround :(
|
// Because onActionViewCollapsed doesn't wanna work we need this workaround :(
|
||||||
|
|
||||||
|
binding?.pluginRecyclerView?.setLinearListLayout(
|
||||||
|
isHorizontal = false,
|
||||||
|
nextDown = FOCUS_SELF,
|
||||||
|
nextRight = FOCUS_SELF,
|
||||||
|
)
|
||||||
|
|
||||||
binding?.pluginRecyclerView?.adapter =
|
binding?.pluginRecyclerView?.adapter =
|
||||||
PluginAdapter {
|
PluginAdapter {
|
||||||
|
@ -167,11 +176,18 @@ class PluginsFragment : Fragment() {
|
||||||
pluginViewModel.updatePluginList(context, url)
|
pluginViewModel.updatePluginList(context, url)
|
||||||
binding?.tvtypesChipsScroll?.root?.isVisible = true
|
binding?.tvtypesChipsScroll?.root?.isVisible = true
|
||||||
|
|
||||||
bindChips(binding?.tvtypesChipsScroll?.tvtypesChips, emptyList(), TvType.values().toList()) { list ->
|
bindChips(
|
||||||
|
binding?.tvtypesChipsScroll?.tvtypesChips,
|
||||||
|
emptyList(),
|
||||||
|
TvType.values().toList(),
|
||||||
|
callback = { list ->
|
||||||
pluginViewModel.tvTypes.clear()
|
pluginViewModel.tvTypes.clear()
|
||||||
pluginViewModel.tvTypes.addAll(list.map { it.name })
|
pluginViewModel.tvTypes.addAll(list.map { it.name })
|
||||||
pluginViewModel.updateFilteredPlugins()
|
pluginViewModel.updateFilteredPlugins()
|
||||||
}
|
},
|
||||||
|
nextFocusDown = R.id.plugin_recycler_view,
|
||||||
|
nextFocusUp = null,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager
|
||||||
import com.lagradost.cloudstream3.syncproviders.SyncAPI
|
import com.lagradost.cloudstream3.syncproviders.SyncAPI
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
import com.lagradost.cloudstream3.ui.WatchType
|
||||||
import com.lagradost.cloudstream3.ui.WhoIsWatchingAdapter
|
import com.lagradost.cloudstream3.ui.WhoIsWatchingAdapter
|
||||||
|
import com.lagradost.cloudstream3.ui.result.FOCUS_SELF
|
||||||
import com.lagradost.cloudstream3.ui.result.UiImage
|
import com.lagradost.cloudstream3.ui.result.UiImage
|
||||||
import com.lagradost.cloudstream3.ui.result.VideoWatchState
|
import com.lagradost.cloudstream3.ui.result.VideoWatchState
|
||||||
import com.lagradost.cloudstream3.ui.result.setImage
|
import com.lagradost.cloudstream3.ui.result.setImage
|
||||||
|
@ -194,7 +195,13 @@ object DataStoreHelper {
|
||||||
builder.setContentView(binding.root)
|
builder.setContentView(binding.root)
|
||||||
val accountName = context.getString(R.string.account)
|
val accountName = context.getString(R.string.account)
|
||||||
|
|
||||||
binding.profilesRecyclerview.setLinearListLayout(isHorizontal = true)
|
binding.profilesRecyclerview.setLinearListLayout(
|
||||||
|
isHorizontal = true,
|
||||||
|
nextUp = FOCUS_SELF,
|
||||||
|
nextDown = FOCUS_SELF,
|
||||||
|
nextLeft = FOCUS_SELF,
|
||||||
|
nextRight = FOCUS_SELF
|
||||||
|
)
|
||||||
binding.profilesRecyclerview.adapter = WhoIsWatchingAdapter(
|
binding.profilesRecyclerview.adapter = WhoIsWatchingAdapter(
|
||||||
selectCallBack = { account ->
|
selectCallBack = { account ->
|
||||||
setAccount(account)
|
setAccount(account)
|
||||||
|
|
|
@ -2,38 +2,39 @@
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:background="?attr/primaryGrayBackground"
|
|
||||||
android:id="@+id/download_child_root"
|
android:id="@+id/download_child_root"
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/primaryGrayBackground"
|
||||||
|
android:orientation="vertical"
|
||||||
tools:context=".ui.download.DownloadFragment">
|
tools:context=".ui.download.DownloadFragment">
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@+id/download_child_toolbar"
|
android:id="@+id/download_child_toolbar"
|
||||||
android:paddingTop="@dimen/navbar_height"
|
android:layout_width="match_parent"
|
||||||
tools:title="Overlord"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/primaryGrayBackground"
|
android:background="?attr/primaryGrayBackground"
|
||||||
|
android:paddingTop="@dimen/navbar_height"
|
||||||
|
app:layout_scrollFlags="scroll|enterAlways"
|
||||||
app:navigationIconTint="?attr/iconColor"
|
app:navigationIconTint="?attr/iconColor"
|
||||||
app:titleTextColor="?attr/textColor"
|
app:titleTextColor="?attr/textColor"
|
||||||
app:layout_scrollFlags="scroll|enterAlways"
|
tools:title="Overlord" />
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:nextFocusUp="@id/download_child_toolbar"
|
|
||||||
|
|
||||||
android:background="?attr/primaryBlackBackground"
|
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
|
||||||
android:padding="10dp"
|
|
||||||
tools:listitem="@layout/download_child_episode"
|
|
||||||
android:id="@+id/download_child_list"
|
android:id="@+id/download_child_list"
|
||||||
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/primaryBlackBackground"
|
||||||
|
android:nextFocusLeft="@id/nav_rail_view"
|
||||||
|
android:nextFocusUp="@id/download_child_toolbar"
|
||||||
|
android:padding="10dp"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
tools:listitem="@layout/download_child_episode" />
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -64,6 +64,7 @@
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:foreground="@drawable/outline_drawable"
|
android:foreground="@drawable/outline_drawable"
|
||||||
android:nextFocusRight="@id/add_repo_button_imageview"
|
android:nextFocusRight="@id/add_repo_button_imageview"
|
||||||
|
android:nextFocusUp="@id/repo_recycler_view"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
|
|
||||||
|
@ -84,13 +85,13 @@
|
||||||
android:textColor="?attr/textColor" />
|
android:textColor="?attr/textColor" />
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
app:cardElevation="0dp"
|
|
||||||
android:elevation="0dp"
|
|
||||||
app:cardMaxElevation="0dp"
|
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="12dp"
|
android:layout_height="12dp"
|
||||||
android:layout_marginBottom="5dp"
|
android:layout_marginBottom="5dp"
|
||||||
app:cardCornerRadius="@dimen/storage_radius">
|
android:elevation="0dp"
|
||||||
|
app:cardCornerRadius="@dimen/storage_radius"
|
||||||
|
app:cardElevation="0dp"
|
||||||
|
app:cardMaxElevation="0dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -203,6 +204,8 @@
|
||||||
android:contentDescription="@string/add_repository"
|
android:contentDescription="@string/add_repository"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:nextFocusLeft="@id/plugin_storage_appbar"
|
android:nextFocusLeft="@id/plugin_storage_appbar"
|
||||||
|
android:nextFocusUp="@id/repo_recycler_view"
|
||||||
|
|
||||||
android:src="@drawable/ic_baseline_add_24"
|
android:src="@drawable/ic_baseline_add_24"
|
||||||
app:tint="?attr/textColor" />
|
app:tint="?attr/textColor" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -25,18 +25,22 @@
|
||||||
app:titleTextColor="?attr/textColor"
|
app:titleTextColor="?attr/textColor"
|
||||||
tools:title="Overlord" />
|
tools:title="Overlord" />
|
||||||
|
|
||||||
<include layout="@layout/tvtypes_chips_scroll" android:id="@+id/tvtypes_chips_scroll" />
|
<include
|
||||||
|
android:id="@+id/tvtypes_chips_scroll"
|
||||||
|
layout="@layout/tvtypes_chips_scroll" />
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:clipToPadding="false"
|
|
||||||
android:id="@+id/plugin_recycler_view"
|
android:id="@+id/plugin_recycler_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:nextFocusLeft="@id/nav_rail_view"
|
||||||
|
android:nextFocusUp="@id/tvtypes_chips"
|
||||||
|
|
||||||
|
android:clipToPadding="false"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
tools:listitem="@layout/repository_item" />
|
tools:listitem="@layout/repository_item" />
|
||||||
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
|
|
@ -248,6 +248,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
style="@style/ResultButtonTV"
|
style="@style/ResultButtonTV"
|
||||||
|
|
||||||
android:nextFocusRight="@id/result_description"
|
android:nextFocusRight="@id/result_description"
|
||||||
|
android:nextFocusUp="@id/result_play_movie"
|
||||||
android:nextFocusDown="@id/result_play_series"
|
android:nextFocusDown="@id/result_play_series"
|
||||||
android:text="@string/play_movie_button"
|
android:text="@string/play_movie_button"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
|
@ -537,10 +538,10 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_gravity="end"
|
|
||||||
android:id="@+id/episodes_shadow"
|
android:id="@+id/episodes_shadow"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="end"
|
||||||
android:clickable="false"
|
android:clickable="false"
|
||||||
android:focusable="false"
|
android:focusable="false"
|
||||||
android:focusableInTouchMode="false"
|
android:focusableInTouchMode="false"
|
||||||
|
@ -552,8 +553,8 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/episode_holder_tv"
|
android:id="@+id/episode_holder_tv"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingStart="@dimen/result_padding"
|
android:paddingStart="@dimen/result_padding"
|
||||||
|
@ -563,15 +564,15 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:ignore="RtlHardcoded"
|
tools:ignore="RtlHardcoded"
|
||||||
tools:visibility="visible">
|
tools:visibility="gone">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:descendantFocusability="afterDescendants"
|
|
||||||
android:id="@+id/result_season_selection"
|
android:id="@+id/result_season_selection"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
|
|
||||||
|
android:descendantFocusability="afterDescendants"
|
||||||
android:nextFocusLeft="@id/result_episodes_show"
|
android:nextFocusLeft="@id/result_episodes_show"
|
||||||
android:nextFocusRight="@id/result_range_selection"
|
android:nextFocusRight="@id/result_range_selection"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
@ -580,11 +581,11 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
tools:listitem="@layout/result_selection" />
|
tools:listitem="@layout/result_selection" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:descendantFocusability="afterDescendants"
|
|
||||||
android:id="@+id/result_range_selection"
|
android:id="@+id/result_range_selection"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
|
android:descendantFocusability="afterDescendants"
|
||||||
|
|
||||||
android:nextFocusLeft="@id/result_season_selection"
|
android:nextFocusLeft="@id/result_season_selection"
|
||||||
android:nextFocusRight="@id/result_dub_selection"
|
android:nextFocusRight="@id/result_dub_selection"
|
||||||
|
@ -595,12 +596,12 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:descendantFocusability="afterDescendants"
|
|
||||||
android:id="@+id/result_dub_selection"
|
android:id="@+id/result_dub_selection"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
|
|
||||||
|
android:descendantFocusability="afterDescendants"
|
||||||
android:nextFocusLeft="@id/result_range_selection"
|
android:nextFocusLeft="@id/result_range_selection"
|
||||||
android:nextFocusRight="@id/result_episodes"
|
android:nextFocusRight="@id/result_episodes"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
@ -618,13 +619,12 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
android:layout_height="50dp" />-->
|
android:layout_height="50dp" />-->
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:descendantFocusability="afterDescendants"
|
|
||||||
android:id="@+id/result_episodes"
|
android:id="@+id/result_episodes"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
|
android:descendantFocusability="afterDescendants"
|
||||||
android:nextFocusLeft="@id/result_dub_selection"
|
android:nextFocusLeft="@id/result_dub_selection"
|
||||||
android:nextFocusRight="@id/result_recommendations_filter_selection"
|
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingVertical="@dimen/result_padding"
|
android:paddingVertical="@dimen/result_padding"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
tools:context=".ui.search.SearchFragment">
|
tools:context=".ui.search.SearchFragment">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -88,7 +88,9 @@
|
||||||
app:tint="?attr/textColor" />
|
app:tint="?attr/textColor" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<include layout="@layout/tvtypes_chips_scroll" android:id="@+id/tvtypes_chips_scroll" />
|
<include
|
||||||
|
android:id="@+id/tvtypes_chips_scroll"
|
||||||
|
layout="@layout/tvtypes_chips_scroll" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,7 +118,10 @@
|
||||||
|
|
||||||
android:background="?attr/primaryBlackBackground"
|
android:background="?attr/primaryBlackBackground"
|
||||||
android:descendantFocusability="afterDescendants"
|
android:descendantFocusability="afterDescendants"
|
||||||
|
|
||||||
android:nextFocusLeft="@id/nav_rail_view"
|
android:nextFocusLeft="@id/nav_rail_view"
|
||||||
|
android:nextFocusUp="@id/tvtypes_chips"
|
||||||
|
android:nextFocusDown="@id/search_clear_call_history"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:listitem="@layout/homepage_parent" />
|
tools:listitem="@layout/homepage_parent" />
|
||||||
|
|
||||||
|
@ -134,20 +139,24 @@
|
||||||
android:background="?attr/primaryBlackBackground"
|
android:background="?attr/primaryBlackBackground"
|
||||||
android:descendantFocusability="afterDescendants"
|
android:descendantFocusability="afterDescendants"
|
||||||
android:nextFocusLeft="@id/nav_rail_view"
|
android:nextFocusLeft="@id/nav_rail_view"
|
||||||
android:visibility="visible"
|
android:nextFocusUp="@id/tvtypes_chips"
|
||||||
|
android:nextFocusDown="@id/search_clear_call_history"
|
||||||
|
|
||||||
android:paddingBottom="50dp"
|
android:paddingBottom="50dp"
|
||||||
|
android:visibility="visible"
|
||||||
tools:listitem="@layout/search_history_item" />
|
tools:listitem="@layout/search_history_item" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/search_clear_call_history"
|
android:id="@+id/search_clear_call_history"
|
||||||
style="@style/BlackButton"
|
style="@style/BlackButton"
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:padding="0dp"
|
|
||||||
app:cornerRadius="0dp"
|
|
||||||
android:layout_margin="0dp"
|
|
||||||
android:text="@string/clear_history"
|
|
||||||
app:icon="@drawable/delete_all"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="50dp" />
|
android:layout_height="50dp"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:nextFocusUp="@id/search_history_recycler"
|
||||||
|
android:padding="0dp"
|
||||||
|
android:text="@string/clear_history"
|
||||||
|
app:cornerRadius="0dp"
|
||||||
|
app:icon="@drawable/delete_all" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -11,11 +11,11 @@
|
||||||
tools:context=".ui.search.SearchFragment">
|
tools:context=".ui.search.SearchFragment">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_marginStart="@dimen/navbar_width"
|
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/navbar_width"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -89,7 +89,9 @@
|
||||||
app:tint="?attr/textColor" />
|
app:tint="?attr/textColor" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<include layout="@layout/tvtypes_chips_scroll" android:id="@+id/tvtypes_chips_scroll" />
|
<include
|
||||||
|
android:id="@+id/tvtypes_chips_scroll"
|
||||||
|
layout="@layout/tvtypes_chips_scroll" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,38 +120,43 @@
|
||||||
android:background="?attr/primaryBlackBackground"
|
android:background="?attr/primaryBlackBackground"
|
||||||
android:descendantFocusability="afterDescendants"
|
android:descendantFocusability="afterDescendants"
|
||||||
android:nextFocusLeft="@id/nav_rail_view"
|
android:nextFocusLeft="@id/nav_rail_view"
|
||||||
|
android:nextFocusUp="@id/tvtypes_chips"
|
||||||
|
android:nextFocusDown="@id/search_clear_call_history"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:listitem="@layout/homepage_parent" />
|
tools:listitem="@layout/homepage_parent" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:background="?attr/primaryBlackBackground"
|
|
||||||
android:id="@+id/search_history_holder"
|
android:id="@+id/search_history_holder"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/primaryBlackBackground">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:layout_marginStart="@dimen/navbar_width"
|
|
||||||
android:id="@+id/search_history_recycler"
|
android:id="@+id/search_history_recycler"
|
||||||
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:descendantFocusability="afterDescendants"
|
android:descendantFocusability="afterDescendants"
|
||||||
android:nextFocusLeft="@id/nav_rail_view"
|
android:nextFocusLeft="@id/nav_rail_view"
|
||||||
android:visibility="visible"
|
android:nextFocusUp="@id/tvtypes_chips"
|
||||||
|
android:nextFocusDown="@id/search_clear_call_history"
|
||||||
android:paddingBottom="50dp"
|
android:paddingBottom="50dp"
|
||||||
|
android:visibility="visible"
|
||||||
tools:listitem="@layout/search_history_item" />
|
tools:listitem="@layout/search_history_item" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:layout_marginStart="@dimen/navbar_width"
|
|
||||||
android:id="@+id/search_clear_call_history"
|
android:id="@+id/search_clear_call_history"
|
||||||
style="@style/BlackButton"
|
style="@style/BlackButton"
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:padding="0dp"
|
|
||||||
app:cornerRadius="0dp"
|
|
||||||
android:layout_margin="0dp"
|
|
||||||
android:text="@string/clear_history"
|
|
||||||
app:icon="@drawable/delete_all"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="50dp" />
|
android:layout_height="50dp"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:layout_margin="0dp"
|
||||||
|
android:layout_marginStart="@dimen/navbar_width"
|
||||||
|
android:nextFocusUp="@id/search_history_recycler"
|
||||||
|
android:padding="0dp"
|
||||||
|
android:text="@string/clear_history"
|
||||||
|
app:cornerRadius="0dp"
|
||||||
|
app:icon="@drawable/delete_all" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -1,19 +1,20 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<com.google.android.material.appbar.AppBarLayout android:background="@android:color/transparent"
|
<com.google.android.material.appbar.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
android:background="@android:color/transparent">
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@+id/settings_toolbar"
|
android:id="@+id/settings_toolbar"
|
||||||
android:paddingTop="@dimen/navbar_height"
|
android:layout_width="match_parent"
|
||||||
tools:title="Overlord"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/primaryGrayBackground"
|
android:background="?attr/primaryGrayBackground"
|
||||||
|
android:descendantFocusability="afterDescendants"
|
||||||
|
android:paddingTop="@dimen/navbar_height"
|
||||||
|
app:layout_scrollFlags="scroll|enterAlways"
|
||||||
app:navigationIconTint="?attr/iconColor"
|
app:navigationIconTint="?attr/iconColor"
|
||||||
app:titleTextColor="?attr/textColor"
|
app:titleTextColor="?attr/textColor"
|
||||||
app:layout_scrollFlags="scroll|enterAlways"
|
tools:title="Overlord" />
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
|
@ -6,6 +6,7 @@
|
||||||
android:paddingStart="8dp"
|
android:paddingStart="8dp"
|
||||||
android:paddingEnd="8dp"
|
android:paddingEnd="8dp"
|
||||||
android:id="@+id/home_select_group"
|
android:id="@+id/home_select_group"
|
||||||
|
android:descendantFocusability="afterDescendants"
|
||||||
app:singleSelection="false"
|
app:singleSelection="false"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<HorizontalScrollView android:id="@+id/tv_types_scroll_view"
|
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/tv_types_scroll_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fadingEdge="horizontal"
|
android:fadingEdge="horizontal"
|
||||||
android:requiresFadingEdge="horizontal"
|
android:requiresFadingEdge="horizontal">
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<include layout="@layout/tvtypes_chips" android:id="@+id/tvtypes_chips" />
|
<include
|
||||||
|
android:descendantFocusability="afterDescendants"
|
||||||
|
android:id="@+id/tvtypes_chips"
|
||||||
|
layout="@layout/tvtypes_chips" />
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
|
@ -5,8 +5,8 @@ buildscript {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("com.android.tools.build:gradle:7.3.1")
|
classpath("com.android.tools.build:gradle:8.0.2")
|
||||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20")
|
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20")
|
||||||
classpath("org.jetbrains.dokka:dokka-gradle-plugin:1.5.0")
|
classpath("org.jetbrains.dokka:dokka-gradle-plugin:1.5.0")
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
||||||
#Fri Apr 30 17:11:15 CEST 2021
|
#Fri Apr 30 17:11:15 CEST 2021
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|
Loading…
Reference in a new issue