testing follow focus on tv

This commit is contained in:
LagradOst 2023-07-24 04:02:05 +02:00
parent 51a6e917b5
commit 3e4a5bdf4c
7 changed files with 164 additions and 62 deletions

View file

@ -83,7 +83,7 @@ object CommonActivity {
val act = activity ?: return val act = activity ?: return
if (message == null) return if (message == null) return
act.runOnUiThread { act.runOnUiThread {
showToast(act, message.asString(act), duration) showToast(act, message.asString(act), duration)
} }
} }
@ -443,63 +443,58 @@ object CommonActivity {
fun dispatchKeyEvent(act: Activity?, event: KeyEvent?): Boolean? { fun dispatchKeyEvent(act: Activity?, event: KeyEvent?): Boolean? {
if (act == null) return null if (act == null) return null
val currentFocus = act.currentFocus
event?.keyCode?.let { keyCode -> event?.keyCode?.let { keyCode ->
when (event.action) { if (currentFocus == null || event.action != KeyEvent.ACTION_DOWN) return@let
KeyEvent.ACTION_DOWN -> { val next = when (keyCode) {
if (act.currentFocus != null) { KeyEvent.KEYCODE_DPAD_LEFT -> getNextFocus(
val next = when (keyCode) { act,
KeyEvent.KEYCODE_DPAD_LEFT -> getNextFocus( currentFocus,
act, FocusDirection.Left
act.currentFocus, )
FocusDirection.Left
)
KeyEvent.KEYCODE_DPAD_RIGHT -> getNextFocus( KeyEvent.KEYCODE_DPAD_RIGHT -> getNextFocus(
act, act,
act.currentFocus, currentFocus,
FocusDirection.Right FocusDirection.Right
) )
KeyEvent.KEYCODE_DPAD_UP -> getNextFocus( KeyEvent.KEYCODE_DPAD_UP -> getNextFocus(
act, act,
act.currentFocus, currentFocus,
FocusDirection.Up FocusDirection.Up
) )
KeyEvent.KEYCODE_DPAD_DOWN -> getNextFocus( KeyEvent.KEYCODE_DPAD_DOWN -> getNextFocus(
act, act,
act.currentFocus, currentFocus,
FocusDirection.Down FocusDirection.Down
) )
else -> null else -> null
} }
if (next != null && next != -1) { if (next != null && next != -1) {
val nextView = act.findViewById<View?>(next) val nextView = act.findViewById<View?>(next)
if (nextView != null) { if (nextView != null) {
nextView.requestFocus() nextView.requestFocus()
keyEventListener?.invoke(Pair(event, true)) keyEventListener?.invoke(Pair(event, true))
return true return true
}
}
when (keyCode) {
KeyEvent.KEYCODE_DPAD_CENTER -> {
if (act.currentFocus is SearchView || act.currentFocus is SearchView.SearchAutoComplete) {
UIHelper.showInputMethod(act.currentFocus?.findFocus())
}
}
}
}
//println("Keycode: $keyCode")
//showToast(
// this,
// "Got Keycode $keyCode | ${KeyEvent.keyCodeToString(keyCode)} \n ${event?.action}",
// Toast.LENGTH_LONG
//)
} }
} }
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER && (act.currentFocus is SearchView || act.currentFocus is SearchView.SearchAutoComplete)) {
UIHelper.showInputMethod(act.currentFocus?.findFocus())
}
//println("Keycode: $keyCode")
//showToast(
// this,
// "Got Keycode $keyCode | ${KeyEvent.keyCodeToString(keyCode)} \n ${event?.action}",
// Toast.LENGTH_LONG
//)
} }
if (keyEventListener?.invoke(Pair(event, false)) == true) { if (keyEventListener?.invoke(Pair(event, false)) == true) {

View file

@ -1,5 +1,7 @@
package com.lagradost.cloudstream3 package com.lagradost.cloudstream3
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@ -11,12 +13,17 @@ import android.os.Bundle
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log import android.util.Log
import android.view.* import android.view.*
import android.view.animation.Animation
import android.view.animation.AnimationSet
import android.widget.LinearLayout
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.doOnLayout
import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
@ -28,12 +35,22 @@ import androidx.navigation.NavOptions
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.transition.ChangeBounds
import androidx.transition.ChangeTransform
import androidx.transition.Scene
import androidx.transition.TransitionManager
import androidx.transition.TransitionManager.beginDelayedTransition
import androidx.transition.TransitionSet
import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.google.android.gms.cast.framework.* import com.google.android.gms.cast.framework.*
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.button.MaterialButton
import com.google.android.material.navigationrail.NavigationRailView import com.google.android.material.navigationrail.NavigationRailView
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
@ -119,6 +136,7 @@ import com.lagradost.nicehttp.ResponseParser
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import java.io.File import java.io.File
import java.lang.ref.WeakReference
import java.net.URI import java.net.URI
import java.net.URLDecoder import java.net.URLDecoder
import java.nio.charset.Charset import java.nio.charset.Charset
@ -553,7 +571,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
} }
} }
override fun dispatchKeyEvent(event: KeyEvent?): Boolean { override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
CommonActivity.dispatchKeyEvent(this, event)?.let { CommonActivity.dispatchKeyEvent(this, event)?.let {
return it return it
@ -728,6 +745,68 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
} }
var binding: ActivityMainBinding? = null var binding: ActivityMainBinding? = null
var focusOutline: WeakReference<View> = WeakReference(null)
var lastFocus: WeakReference<View> = WeakReference(null)
val layoutListener: View.OnLayoutChangeListener =
View.OnLayoutChangeListener { v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
updateFocusView(
v
)
}
private fun updateFocusView(newFocus: View?) {
val focusOutline = focusOutline.get() ?: return
//lastFocus.get()?.removeOnLayoutChangeListener(layoutListener)
val wasGone = focusOutline.isGone
focusOutline.isVisible =
newFocus != null && newFocus.measuredHeight > 0 && newFocus.measuredWidth > 0 && newFocus.isVisible && newFocus !is MaterialButton
if (newFocus != null) {
lastFocus = WeakReference(newFocus)
val out = IntArray(2)
newFocus.getLocationInWindow(out)
val (x, y) = out
/*(newFocus.parent as? RecyclerView)?.let { recycle ->
println("PARET IS RECYLE")
val position = recycle.getChildAdapterPosition(newFocus)
recycle.scrollToPosition(position)
(recycle.layoutManager as? GridLayoutManager)?.let {
if(it.orientation == LinearLayout.HORIZONTAL) {
println("SCROLL")
}
}
}*/
// newFocus.addOnLayoutChangeListener(layoutListener)
// val set = AnimationSet(true)
if(!wasGone) {
(focusOutline.parent as? ViewGroup)?.let {
TransitionManager.endTransitions(it)
TransitionManager.beginDelayedTransition(
it,
TransitionSet().addTransition(ChangeBounds())
.addTransition(ChangeTransform())
.setDuration(100)
)
}
}
// ObjectAnimator.ofFloat(focusOutline, "translationX",focusOutline.translationX, x.toFloat()
focusOutline.layoutParams = focusOutline.layoutParams?.apply {
width = newFocus.measuredWidth
height = newFocus.measuredHeight
}
focusOutline.translationX = x.toFloat()
focusOutline.translationY = y.toFloat()
}
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
app.initClient(this) app.initClient(this)
@ -763,12 +842,12 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
// 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 { try {
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() backup()
} }
} catch (t : Throwable) { } catch (t: Throwable) {
logError(t) logError(t)
} }
@ -777,6 +856,15 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
if (isTvSettings()) { if (isTvSettings()) {
val newLocalBinding = ActivityMainTvBinding.inflate(layoutInflater, null, false) val newLocalBinding = ActivityMainTvBinding.inflate(layoutInflater, null, false)
setContentView(newLocalBinding.root) setContentView(newLocalBinding.root)
focusOutline = WeakReference(newLocalBinding.focusOutline)
newLocalBinding.root.viewTreeObserver.addOnGlobalFocusChangeListener { _, newFocus ->
// println("refocus $oldFocus -> $newFocus")
updateFocusView(newFocus)
}
newLocalBinding.root.viewTreeObserver.addOnScrollChangedListener {
updateFocusView(lastFocus.get())
}
ActivityMainBinding.bind(newLocalBinding.root) // this may crash ActivityMainBinding.bind(newLocalBinding.root) // this may crash
} else { } else {
val newLocalBinding = ActivityMainBinding.inflate(layoutInflater, null, false) val newLocalBinding = ActivityMainBinding.inflate(layoutInflater, null, false)
@ -816,7 +904,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
if (PluginManager.checkSafeModeFile()) { if (PluginManager.checkSafeModeFile()) {
normalSafeApiCall { normalSafeApiCall {
showToast( R.string.safe_mode_file, Toast.LENGTH_LONG) showToast(R.string.safe_mode_file, Toast.LENGTH_LONG)
} }
} else if (lastError == null) { } else if (lastError == null) {
ioSafe { ioSafe {

View file

@ -2,9 +2,11 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android" > <shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke android:width="2dp" <stroke android:width="2dp"
android:color="?attr/white"/> android:color="?attr/white"/>
<corners <!-- <corners
android:bottomLeftRadius="@dimen/rounded_image_radius" android:bottomLeftRadius="@dimen/rounded_image_radius"
android:bottomRightRadius="@dimen/rounded_image_radius" android:bottomRightRadius="@dimen/rounded_image_radius"
android:topLeftRadius="@dimen/rounded_image_radius" android:topLeftRadius="@dimen/rounded_image_radius"
android:topRightRadius="@dimen/rounded_image_radius" /> android:topRightRadius="@dimen/rounded_image_radius" />
-->
</shape> </shape>

View file

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

View file

@ -77,4 +77,21 @@
tools:ignore="FragmentTagUsage" /> tools:ignore="FragmentTagUsage" />
</LinearLayout> </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
android:visibility="gone"
android:id="@+id/focus_outline"
android:src="@drawable/outline"
android:layout_width="100dp"
android:layout_height="100dp">
</ImageView>
</FrameLayout>
</FrameLayout> </FrameLayout>

View file

@ -35,11 +35,10 @@
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/home_preview_change_api" android:id="@+id/home_preview_change_api"
style="@style/BlackButton" style="@style/RegularButtonTV"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_gravity="top|start" android:layout_gravity="top|start"
android:layout_marginStart="@dimen/navbar_width" android:layout_marginStart="@dimen/navbar_width"
android:backgroundTint="@color/semiWhite"
android:minWidth="150dp" /> android:minWidth="150dp" />
</FrameLayout> </FrameLayout>
@ -92,7 +91,7 @@
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/home_preview_play_btt" android:id="@+id/home_preview_play_btt"
style="@style/WhiteButton" style="@style/RegularButtonTV"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_margin="0dp" android:layout_margin="0dp"
android:minWidth="150dp" android:minWidth="150dp"
@ -105,7 +104,7 @@
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/home_preview_info_btt" android:id="@+id/home_preview_info_btt"
style="@style/BlackButton" style="@style/RegularButtonTV"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:minWidth="150dp" android:minWidth="150dp"

View file

@ -85,7 +85,8 @@
<style name="ChipFilled" parent="@style/Widget.Material3.Chip.Filter"> <style name="ChipFilled" parent="@style/Widget.Material3.Chip.Filter">
<item name="chipBackgroundColor">@color/chip_color</item> <item name="chipBackgroundColor">@color/chip_color</item>
<item name="chipStrokeColor">@color/white_transparent_toggle</item> <!-- <item name="chipStrokeColor">@color/white_transparent_toggle</item>-->
<item name="chipStrokeColor">@color/transparent</item>
<item name="chipStrokeWidth">2dp</item> <item name="chipStrokeWidth">2dp</item>
<item name="textColor">@color/chip_color_text</item> <item name="textColor">@color/chip_color_text</item>
<item name="android:textColor">@color/chip_color_text</item> <item name="android:textColor">@color/chip_color_text</item>