From 45e45a3c5ba80923de56e05839e7a90260252ae7 Mon Sep 17 00:00:00 2001 From: Mioki <22417711+okibcn@users.noreply.github.com> Date: Mon, 26 Jan 2026 19:53:09 -0800 Subject: [PATCH 01/11] debug build --- .github/workflows/debugBuild.yml | 85 ++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 .github/workflows/debugBuild.yml diff --git a/.github/workflows/debugBuild.yml b/.github/workflows/debugBuild.yml new file mode 100644 index 00000000000..7ceacd5a7c4 --- /dev/null +++ b/.github/workflows/debugBuild.yml @@ -0,0 +1,85 @@ +name: Debug Build + +on: + push: + paths-ignore: + - '*.md' + workflow_dispatch: + paths-ignore: + - '*.md' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Check if keystore secret exists + id: check_secret + env: + KEYSTORE_SECRET: ${{ secrets.DEBUG_KEYSTORE_BASE64 }} + run: | + if [ -z "$KEYSTORE_SECRET" ]; then + echo "exists=false" >> $GITHUB_OUTPUT + else + echo "exists=true" >> $GITHUB_OUTPUT + fi + + - name: Generate debug keystore + if: steps.check_secret.outputs.exists == 'false' + run: | + keytool -genkey -v \ + -keystore debug.keystore \ + -storepass android \ + -keypass android \ + -alias androiddebugkey \ + -keyalg RSA -keysize 2048 -validity 10000 \ + -dname "C=US, O=Android, CN=Android Debug" + base64 debug.keystore > debug.keystore.base64 + echo "NO DEBUG KEY FOUND!!!" + echo "Use this one as DEBUG_KEYSTORE_BASE64 in the repo Settings > Secrets and variables > Actions" + cat debug.keystore.base64 + + - name: Decode debug keystore AND Move it to expected location and name + if: steps.check_secret.outputs.exists == 'true' + run: | + mkdir -p ~/work/_temp/keystore/ + echo "${{ secrets.DEBUG_KEYSTORE_BASE64 }}" | base64 -d > ~/work/_temp/keystore/prerelease.keystore + + - name: Setup signing env vars + if: steps.check_secret.outputs.exists == 'true' + run: | + echo "SIGNING_STORE_PASSWORD=android" >> $GITHUB_ENV + echo "SIGNING_KEY_PASSWORD=android" >> $GITHUB_ENV + echo "SIGNING_KEY_ALIAS=androiddebugkey" >> $GITHUB_ENV + + - name: Force debug signingConfig + if: steps.check_secret.outputs.exists == 'true' + run: | + sed -i 's/debug {/debug {\n signingConfig = signingConfigs.getByName("prerelease")\n /' app/build.gradle.kts + + - name: Set up JDK 17 + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: 17 + + - name: Setup Android SDK + uses: android-actions/setup-android@v3.2.2 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v5 + with: + cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + cache-read-only: false + + - name: Run Gradle + run: ./gradlew assemblePrereleaseDebug + + - name: Upload Artifact + uses: actions/upload-artifact@v6 + with: + name: debug-build + path: "app/build/outputs/apk/prerelease/debug/*.apk" From ea735fdd7902a0698d3f7a3b1c928bd933543e08 Mon Sep 17 00:00:00 2001 From: Mioki <22417711+okibcn@users.noreply.github.com> Date: Mon, 26 Jan 2026 19:53:50 -0800 Subject: [PATCH 02/11] no android sdk in debug build --- .github/workflows/debugBuild.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/debugBuild.yml b/.github/workflows/debugBuild.yml index 7ceacd5a7c4..30b2b6a20d6 100644 --- a/.github/workflows/debugBuild.yml +++ b/.github/workflows/debugBuild.yml @@ -66,9 +66,6 @@ jobs: distribution: temurin java-version: 17 - - name: Setup Android SDK - uses: android-actions/setup-android@v3.2.2 - - name: Setup Gradle uses: gradle/actions/setup-gradle@v5 with: From 9114923a6f088e3c1ff9fe6004c7d997701ff45b Mon Sep 17 00:00:00 2001 From: Mioki <22417711+okibcn@users.noreply.github.com> Date: Fri, 30 Jan 2026 11:34:58 -0800 Subject: [PATCH 03/11] adds onBackPressed() to HomeFragment.kt --- .../cloudstream3/ui/home/HomeFragment.kt | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index 49c6d0d7732..3570eacaf16 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -570,6 +570,60 @@ class HomeFragment : BaseFragment( super.onDestroyView() } + override fun onBackPressed(): Boolean { + // Solo actuar en interfaz TV + if (!isLayout(TV)) { + return false // Comportamiento normal en móvil + } + + val currentFocus = activity?.currentFocus + + // Si no hay enfoque, comportamiento normal + if (currentFocus == null) { + return false + } + + // Verificar si el enfoque está en algún elemento del contenido (RecyclerView) + var parent = currentFocus.parent + var isInHomeContent = false + + // Recorremos los padres del view con enfoque + while (parent != null) { + if (parent.id == R.id.home_master_recycler) { + isInHomeContent = true + break + } + parent = parent.parent + } + + // Si está en el contenido, mover foco al selector de extensión + if (isInHomeContent) { + binding?.homeChangeApi?.let { changeApiButton -> + if (changeApiButton.isFocusable) { + // Hacer scroll al top primero + binding?.homeMasterRecycler?.smoothScrollToPosition(0) + // Enfocar el selector de extensión + changeApiButton.requestFocus() + return true // Consumimos el evento Back + } + } + } + + // Verificar si el enfoque está en el botón selector de extensión + if (currentFocus.id == R.id.home_change_api) { + // Mover enfoque al icono de home en la navegación + activity?.findViewById(R.id.navigation_home)?.let { homeNav -> + if (homeNav.isFocusable) { + homeNav.requestFocus() + return true // Consumimos el evento Back + } + } + } + + // En cualquier otro caso, comportamiento normal + return false + } + private val apiChangeClickListener = View.OnClickListener { view -> view.context.selectHomepage(currentApiName) { api -> homeViewModel.loadAndCancel(api, forceReload = true, fromUI = true) From 698fff79d46eb7d9930463d899d74a2d5aa85b39 Mon Sep 17 00:00:00 2001 From: Mioki <22417711+okibcn@users.noreply.github.com> Date: Fri, 30 Jan 2026 12:41:08 -0800 Subject: [PATCH 04/11] first fixes --- .../java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index 3570eacaf16..cd52e075f69 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -570,7 +570,7 @@ class HomeFragment : BaseFragment( super.onDestroyView() } - override fun onBackPressed(): Boolean { + fun onBackPressed(): Boolean { // Solo actuar en interfaz TV if (!isLayout(TV)) { return false // Comportamiento normal en móvil @@ -589,7 +589,7 @@ class HomeFragment : BaseFragment( // Recorremos los padres del view con enfoque while (parent != null) { - if (parent.id == R.id.home_master_recycler) { + if (parent is View && parent.id == R.id.home_master_recycler) { isInHomeContent = true break } @@ -624,6 +624,7 @@ class HomeFragment : BaseFragment( return false } + private val apiChangeClickListener = View.OnClickListener { view -> view.context.selectHomepage(currentApiName) { api -> homeViewModel.loadAndCancel(api, forceReload = true, fromUI = true) From bb054323f6ed1a6c4e60176793daab786c84dba4 Mon Sep 17 00:00:00 2001 From: Mioki <22417711+okibcn@users.noreply.github.com> Date: Fri, 30 Jan 2026 12:56:43 -0800 Subject: [PATCH 05/11] Solution 2 --- .../cloudstream3/ui/home/HomeFragment.kt | 124 ++++++++++-------- 1 file changed, 68 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index cd52e075f69..935cce49bfe 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -76,6 +76,11 @@ import com.lagradost.cloudstream3.utils.UIHelper.navigate import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes import com.lagradost.cloudstream3.utils.UIHelper.toPx +import androidx.activity.ComponentActivity +import com.lagradost.cloudstream3.utils.BackPressedCallbackHelper +import com.lagradost.cloudstream3.utils.BackPressedCallbackHelper.attachBackPressedCallback +import com.lagradost.cloudstream3.utils.BackPressedCallbackHelper.detachBackPressedCallback + private const val TAG = "HomeFragment" class HomeFragment : BaseFragment( @@ -566,64 +571,10 @@ class HomeFragment : BaseFragment( } override fun onDestroyView() { + (activity as? ComponentActivity)?.detachBackPressedCallback("HomeFragment_BackPress") bottomSheetDialog?.ownHide() super.onDestroyView() - } - - fun onBackPressed(): Boolean { - // Solo actuar en interfaz TV - if (!isLayout(TV)) { - return false // Comportamiento normal en móvil - } - - val currentFocus = activity?.currentFocus - - // Si no hay enfoque, comportamiento normal - if (currentFocus == null) { - return false - } - - // Verificar si el enfoque está en algún elemento del contenido (RecyclerView) - var parent = currentFocus.parent - var isInHomeContent = false - - // Recorremos los padres del view con enfoque - while (parent != null) { - if (parent is View && parent.id == R.id.home_master_recycler) { - isInHomeContent = true - break - } - parent = parent.parent - } - - // Si está en el contenido, mover foco al selector de extensión - if (isInHomeContent) { - binding?.homeChangeApi?.let { changeApiButton -> - if (changeApiButton.isFocusable) { - // Hacer scroll al top primero - binding?.homeMasterRecycler?.smoothScrollToPosition(0) - // Enfocar el selector de extensión - changeApiButton.requestFocus() - return true // Consumimos el evento Back - } - } - } - - // Verificar si el enfoque está en el botón selector de extensión - if (currentFocus.id == R.id.home_change_api) { - // Mover enfoque al icono de home en la navegación - activity?.findViewById(R.id.navigation_home)?.let { homeNav -> - if (homeNav.isFocusable) { - homeNav.requestFocus() - return true // Consumimos el evento Back - } - } - } - - // En cualquier otro caso, comportamiento normal - return false - } - + } private val apiChangeClickListener = View.OnClickListener { view -> view.context.selectHomepage(currentApiName) { api -> @@ -681,6 +632,10 @@ class HomeFragment : BaseFragment( @SuppressLint("SetTextI18n") override fun onBindingCreated(binding: FragmentHomeBinding) { context?.let { HomeChildItemAdapter.updatePosterSize(it) } + // NUEVO: Registrar callback para botón Back en TV + (activity as? ComponentActivity)?.attachBackPressedCallback("HomeFragment_BackPress") { + handleTvBackPress(this) + } binding.apply { //homeChangeApiLoading.setOnClickListener(apiChangeClickListener) //homeChangeApiLoading.setOnClickListener(apiChangeClickListener) @@ -939,4 +894,61 @@ class HomeFragment : BaseFragment( } }*/ } + + private fun handleTvBackPress(helper: BackPressedCallbackHelper.CallbackHelper) { + // Solo actuar en interfaz TV + if (!isLayout(TV)) { + helper.runDefault() + return + } + + val currentFocus = activity?.currentFocus + + // Si no hay enfoque, comportamiento normal + if (currentFocus == null) { + helper.runDefault() + return + } + + // Verificar si el enfoque está en algún elemento del contenido (RecyclerView) + var parent = currentFocus.parent + var isInHomeContent = false + + // Recorremos los padres del view con enfoque + while (parent != null) { + if (parent is View && parent.id == R.id.home_master_recycler) { + isInHomeContent = true + break + } + parent = parent.parent + } + + // Si está en el contenido, mover foco al selector de extensión + if (isInHomeContent) { + binding?.homeChangeApi?.let { changeApiButton -> + if (changeApiButton.isFocusable) { + // Hacer scroll al top primero + binding?.homeMasterRecycler?.smoothScrollToPosition(0) + // Enfocar el selector de extensión + changeApiButton.requestFocus() + return // Consumimos el evento Back + } + } + } + + // Verificar si el enfoque está en el botón selector de extensión + if (currentFocus.id == R.id.home_change_api) { + // Mover enfoque al icono de home en la navegación + activity?.findViewById(R.id.navigation_home)?.let { homeNav -> + if (homeNav.isFocusable) { + homeNav.requestFocus() + return // Consumimos el evento Back + } + } + } + + // En cualquier otro caso, comportamiento normal + helper.runDefault() + } + } From e7076f77981e4ebc42445c83c30074027d36b023 Mon Sep 17 00:00:00 2001 From: Mioki <22417711+okibcn@users.noreply.github.com> Date: Fri, 30 Jan 2026 13:25:50 -0800 Subject: [PATCH 06/11] Removes debugBuild --- .github/workflows/debugBuild.yml | 82 -------------------------------- 1 file changed, 82 deletions(-) delete mode 100644 .github/workflows/debugBuild.yml diff --git a/.github/workflows/debugBuild.yml b/.github/workflows/debugBuild.yml deleted file mode 100644 index 30b2b6a20d6..00000000000 --- a/.github/workflows/debugBuild.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: Debug Build - -on: - push: - paths-ignore: - - '*.md' - workflow_dispatch: - paths-ignore: - - '*.md' - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Check if keystore secret exists - id: check_secret - env: - KEYSTORE_SECRET: ${{ secrets.DEBUG_KEYSTORE_BASE64 }} - run: | - if [ -z "$KEYSTORE_SECRET" ]; then - echo "exists=false" >> $GITHUB_OUTPUT - else - echo "exists=true" >> $GITHUB_OUTPUT - fi - - - name: Generate debug keystore - if: steps.check_secret.outputs.exists == 'false' - run: | - keytool -genkey -v \ - -keystore debug.keystore \ - -storepass android \ - -keypass android \ - -alias androiddebugkey \ - -keyalg RSA -keysize 2048 -validity 10000 \ - -dname "C=US, O=Android, CN=Android Debug" - base64 debug.keystore > debug.keystore.base64 - echo "NO DEBUG KEY FOUND!!!" - echo "Use this one as DEBUG_KEYSTORE_BASE64 in the repo Settings > Secrets and variables > Actions" - cat debug.keystore.base64 - - - name: Decode debug keystore AND Move it to expected location and name - if: steps.check_secret.outputs.exists == 'true' - run: | - mkdir -p ~/work/_temp/keystore/ - echo "${{ secrets.DEBUG_KEYSTORE_BASE64 }}" | base64 -d > ~/work/_temp/keystore/prerelease.keystore - - - name: Setup signing env vars - if: steps.check_secret.outputs.exists == 'true' - run: | - echo "SIGNING_STORE_PASSWORD=android" >> $GITHUB_ENV - echo "SIGNING_KEY_PASSWORD=android" >> $GITHUB_ENV - echo "SIGNING_KEY_ALIAS=androiddebugkey" >> $GITHUB_ENV - - - name: Force debug signingConfig - if: steps.check_secret.outputs.exists == 'true' - run: | - sed -i 's/debug {/debug {\n signingConfig = signingConfigs.getByName("prerelease")\n /' app/build.gradle.kts - - - name: Set up JDK 17 - uses: actions/setup-java@v5 - with: - distribution: temurin - java-version: 17 - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v5 - with: - cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} - cache-read-only: false - - - name: Run Gradle - run: ./gradlew assemblePrereleaseDebug - - - name: Upload Artifact - uses: actions/upload-artifact@v6 - with: - name: debug-build - path: "app/build/outputs/apk/prerelease/debug/*.apk" From 87a0b67ff2b23e902b165ff7952b59daf983b965 Mon Sep 17 00:00:00 2001 From: Mioki <22417711+okibcn@users.noreply.github.com> Date: Fri, 30 Jan 2026 13:53:57 -0800 Subject: [PATCH 07/11] handleTvBackPress optimization --- .../cloudstream3/ui/home/HomeFragment.kt | 56 ++++++------------- 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index 935cce49bfe..fbd5604885b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -75,7 +75,6 @@ import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount import com.lagradost.cloudstream3.utils.UIHelper.navigate import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes import com.lagradost.cloudstream3.utils.UIHelper.toPx - import androidx.activity.ComponentActivity import com.lagradost.cloudstream3.utils.BackPressedCallbackHelper import com.lagradost.cloudstream3.utils.BackPressedCallbackHelper.attachBackPressedCallback @@ -574,7 +573,7 @@ class HomeFragment : BaseFragment( (activity as? ComponentActivity)?.detachBackPressedCallback("HomeFragment_BackPress") bottomSheetDialog?.ownHide() super.onDestroyView() - } + } private val apiChangeClickListener = View.OnClickListener { view -> view.context.selectHomepage(currentApiName) { api -> @@ -632,7 +631,6 @@ class HomeFragment : BaseFragment( @SuppressLint("SetTextI18n") override fun onBindingCreated(binding: FragmentHomeBinding) { context?.let { HomeChildItemAdapter.updatePosterSize(it) } - // NUEVO: Registrar callback para botón Back en TV (activity as? ComponentActivity)?.attachBackPressedCallback("HomeFragment_BackPress") { handleTvBackPress(this) } @@ -896,59 +894,37 @@ class HomeFragment : BaseFragment( } private fun handleTvBackPress(helper: BackPressedCallbackHelper.CallbackHelper) { - // Solo actuar en interfaz TV + // Only apply custom behavior on TV interface if (!isLayout(TV)) { helper.runDefault() return } - - val currentFocus = activity?.currentFocus - - // Si no hay enfoque, comportamiento normal - if (currentFocus == null) { + val currentFocus = activity?.currentFocus ?: run { helper.runDefault() return } - - // Verificar si el enfoque está en algún elemento del contenido (RecyclerView) + // sInsideRecycle is true when focus is inside home_master_recycler var parent = currentFocus.parent - var isInHomeContent = false - - // Recorremos los padres del view con enfoque + var isInsideRecycler = false while (parent != null) { if (parent is View && parent.id == R.id.home_master_recycler) { - isInHomeContent = true + isInsideRecycler = true break } parent = parent.parent } - - // Si está en el contenido, mover foco al selector de extensión - if (isInHomeContent) { - binding?.homeChangeApi?.let { changeApiButton -> - if (changeApiButton.isFocusable) { - // Hacer scroll al top primero - binding?.homeMasterRecycler?.smoothScrollToPosition(0) - // Enfocar el selector de extensión - changeApiButton.requestFocus() - return // Consumimos el evento Back - } + when { + // Case 1: Focus is within plugin content -> Move to plugin selector + isInsideRecycler -> { + binding?.homeMasterRecycler?.smoothScrollToPosition(0) + binding?.homeChangeApi?.requestFocus() } - } - - // Verificar si el enfoque está en el botón selector de extensión - if (currentFocus.id == R.id.home_change_api) { - // Mover enfoque al icono de home en la navegación - activity?.findViewById(R.id.navigation_home)?.let { homeNav -> - if (homeNav.isFocusable) { - homeNav.requestFocus() - return // Consumimos el evento Back - } + // Case 2: Focus is on plugin selector -> Move to home navigation + currentFocus.id == R.id.home_change_api -> { + activity?.findViewById(R.id.navigation_home)?.requestFocus() } + // Case 3: Any other location -> Use default back behavior + else -> helper.runDefault() } - - // En cualquier otro caso, comportamiento normal - helper.runDefault() } - } From 59f06dd58a69be25456e122e665a03db4de78307 Mon Sep 17 00:00:00 2001 From: Mioki <22417711+okibcn@users.noreply.github.com> Date: Fri, 30 Jan 2026 14:05:34 -0800 Subject: [PATCH 08/11] Properly sorted required imports --- .../com/lagradost/cloudstream3/ui/home/HomeFragment.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index fbd5604885b..bcf75355be6 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -64,6 +64,9 @@ import com.lagradost.cloudstream3.utils.AppContextUtils.loadSearchResult import com.lagradost.cloudstream3.utils.AppContextUtils.ownHide import com.lagradost.cloudstream3.utils.AppContextUtils.ownShow import com.lagradost.cloudstream3.utils.AppContextUtils.setDefaultFocus +import com.lagradost.cloudstream3.utils.BackPressedCallbackHelper +import com.lagradost.cloudstream3.utils.BackPressedCallbackHelper.attachBackPressedCallback +import com.lagradost.cloudstream3.utils.BackPressedCallbackHelper.detachBackPressedCallback import com.lagradost.cloudstream3.utils.Coroutines.ioSafe import com.lagradost.cloudstream3.utils.DataStoreHelper import com.lagradost.cloudstream3.utils.EmptyEvent @@ -75,10 +78,6 @@ import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount import com.lagradost.cloudstream3.utils.UIHelper.navigate import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes import com.lagradost.cloudstream3.utils.UIHelper.toPx -import androidx.activity.ComponentActivity -import com.lagradost.cloudstream3.utils.BackPressedCallbackHelper -import com.lagradost.cloudstream3.utils.BackPressedCallbackHelper.attachBackPressedCallback -import com.lagradost.cloudstream3.utils.BackPressedCallbackHelper.detachBackPressedCallback private const val TAG = "HomeFragment" @@ -903,7 +902,7 @@ class HomeFragment : BaseFragment( helper.runDefault() return } - // sInsideRecycle is true when focus is inside home_master_recycler + // isInsideRecycle is true when focus is inside home_master_recycler var parent = currentFocus.parent var isInsideRecycler = false while (parent != null) { From 3548ad66ae2f84ebf75b1ae3279eadfe2e9d4b2d Mon Sep 17 00:00:00 2001 From: Mioki <22417711+okibcn@users.noreply.github.com> Date: Fri, 30 Jan 2026 14:16:00 -0800 Subject: [PATCH 09/11] Missing import --- .../main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index bcf75355be6..3a67c4609e6 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -15,6 +15,7 @@ import android.widget.ImageView import android.widget.ListView import android.widget.TextView import android.widget.Toast +import androidx.activity.ComponentActivity import androidx.appcompat.app.AlertDialog import androidx.core.net.toUri import androidx.core.view.isGone From 3b9fc2bd30c466ea6b6718e373ee84a1853ec7e3 Mon Sep 17 00:00:00 2001 From: Mioki <22417711+okibcn@users.noreply.github.com> Date: Fri, 30 Jan 2026 14:39:09 -0800 Subject: [PATCH 10/11] Add BackButton to reload provider and search button --- .../com/lagradost/cloudstream3/ui/home/HomeFragment.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index 3a67c4609e6..189ee0bf322 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -903,7 +903,7 @@ class HomeFragment : BaseFragment( helper.runDefault() return } - // isInsideRecycle is true when focus is inside home_master_recycler + // Check if focus is inside home_master_recycler var parent = currentFocus.parent var isInsideRecycler = false while (parent != null) { @@ -918,9 +918,11 @@ class HomeFragment : BaseFragment( isInsideRecycler -> { binding?.homeMasterRecycler?.smoothScrollToPosition(0) binding?.homeChangeApi?.requestFocus() - } - // Case 2: Focus is on plugin selector -> Move to home navigation - currentFocus.id == R.id.home_change_api -> { + } + // Case 2: Focus is on plugin selector or nearby buttons -> Move to home navigation + currentFocus.id == R.id.home_change_api || + currentFocus.id == R.id.home_preview_reload_provider || + currentFocus.id == R.id.home_preview_search_button -> { activity?.findViewById(R.id.navigation_home)?.requestFocus() } // Case 3: Any other location -> Use default back behavior From b1f42d4c6055d762f65f87959396c03fccd944fb Mon Sep 17 00:00:00 2001 From: Mioki <22417711+okibcn@users.noreply.github.com> Date: Thu, 5 Feb 2026 21:30:01 -0800 Subject: [PATCH 11/11] Swap Focus and Scroll --- .../java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index 189ee0bf322..69d420b8205 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -916,8 +916,8 @@ class HomeFragment : BaseFragment( when { // Case 1: Focus is within plugin content -> Move to plugin selector isInsideRecycler -> { - binding?.homeMasterRecycler?.smoothScrollToPosition(0) binding?.homeChangeApi?.requestFocus() + binding?.homeMasterRecycler?.smoothScrollToPosition(0) } // Case 2: Focus is on plugin selector or nearby buttons -> Move to home navigation currentFocus.id == R.id.home_change_api ||