refactor: overall navigation mechanism and split logic #1429 (#1430)

This commit is contained in:
IndusAryan
2025-03-01 05:11:14 +05:30
committed by GitHub
parent ab23f23c71
commit 1c6db0e514
15 changed files with 198 additions and 182 deletions

View File

@ -1,78 +1,78 @@
name: Archive build
on:
push:
branches: [ master ]
paths-ignore:
- '*.md'
- '*.json'
- '**/wcokey.txt'
workflow_dispatch:
concurrency:
group: "Archive-build"
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Generate access token
id: generate_token
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_KEY }}
repository: "recloudstream/secrets"
- name: Generate access token (archive)
id: generate_archive_token
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_KEY }}
repository: "recloudstream/cloudstream-archive"
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'adopt'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Fetch keystore
id: fetch_keystore
run: |
TMP_KEYSTORE_FILE_PATH="${RUNNER_TEMP}"/keystore
mkdir -p "${TMP_KEYSTORE_FILE_PATH}"
curl -H "Authorization: token ${{ steps.generate_token.outputs.token }}" -o "${TMP_KEYSTORE_FILE_PATH}/prerelease_keystore.keystore" "https://raw.githubusercontent.com/recloudstream/secrets/master/keystore.jks"
curl -H "Authorization: token ${{ steps.generate_token.outputs.token }}" -o "keystore_password.txt" "https://raw.githubusercontent.com/recloudstream/secrets/master/keystore_password.txt"
KEY_PWD="$(cat keystore_password.txt)"
echo "::add-mask::${KEY_PWD}"
echo "key_pwd=$KEY_PWD" >> $GITHUB_OUTPUT
- name: Run Gradle
run: |
./gradlew assemblePrerelease
env:
SIGNING_KEY_ALIAS: "key0"
SIGNING_KEY_PASSWORD: ${{ steps.fetch_keystore.outputs.key_pwd }}
SIGNING_STORE_PASSWORD: ${{ steps.fetch_keystore.outputs.key_pwd }}
SIMKL_CLIENT_ID: ${{ secrets.SIMKL_CLIENT_ID }}
SIMKL_CLIENT_SECRET: ${{ secrets.SIMKL_CLIENT_SECRET }}
- uses: actions/checkout@v4
with:
repository: "recloudstream/cloudstream-archive"
token: ${{ steps.generate_archive_token.outputs.token }}
path: "archive"
- name: Move build
run: |
cp app/build/outputs/apk/prerelease/release/*.apk "archive/$(git rev-parse --short HEAD).apk"
- name: Push archive
run: |
cd $GITHUB_WORKSPACE/archive
git config --local user.email "actions@github.com"
git config --local user.name "GitHub Actions"
git add .
git commit --amend -m "Build $GITHUB_SHA" || exit 0 # do not error if nothing to commit
name: Archive build
on:
push:
branches: [ master ]
paths-ignore:
- '*.md'
- '*.json'
- '**/wcokey.txt'
workflow_dispatch:
concurrency:
group: "Archive-build"
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Generate access token
id: generate_token
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_KEY }}
repository: "recloudstream/secrets"
- name: Generate access token (archive)
id: generate_archive_token
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_KEY }}
repository: "recloudstream/cloudstream-archive"
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'adopt'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Fetch keystore
id: fetch_keystore
run: |
TMP_KEYSTORE_FILE_PATH="${RUNNER_TEMP}"/keystore
mkdir -p "${TMP_KEYSTORE_FILE_PATH}"
curl -H "Authorization: token ${{ steps.generate_token.outputs.token }}" -o "${TMP_KEYSTORE_FILE_PATH}/prerelease_keystore.keystore" "https://raw.githubusercontent.com/recloudstream/secrets/master/keystore.jks"
curl -H "Authorization: token ${{ steps.generate_token.outputs.token }}" -o "keystore_password.txt" "https://raw.githubusercontent.com/recloudstream/secrets/master/keystore_password.txt"
KEY_PWD="$(cat keystore_password.txt)"
echo "::add-mask::${KEY_PWD}"
echo "key_pwd=$KEY_PWD" >> $GITHUB_OUTPUT
- name: Run Gradle
run: |
./gradlew assemblePrerelease
env:
SIGNING_KEY_ALIAS: "key0"
SIGNING_KEY_PASSWORD: ${{ steps.fetch_keystore.outputs.key_pwd }}
SIGNING_STORE_PASSWORD: ${{ steps.fetch_keystore.outputs.key_pwd }}
SIMKL_CLIENT_ID: ${{ secrets.SIMKL_CLIENT_ID }}
SIMKL_CLIENT_SECRET: ${{ secrets.SIMKL_CLIENT_SECRET }}
- uses: actions/checkout@v4
with:
repository: "recloudstream/cloudstream-archive"
token: ${{ steps.generate_archive_token.outputs.token }}
path: "archive"
- name: Move build
run: |
cp app/build/outputs/apk/prerelease/release/*.apk "archive/$(git rev-parse --short HEAD).apk"
- name: Push archive
run: |
cd $GITHUB_WORKSPACE/archive
git config --local user.email "actions@github.com"
git config --local user.name "GitHub Actions"
git add .
git commit --amend -m "Build $GITHUB_SHA" || exit 0 # do not error if nothing to commit
git push --force

View File

@ -197,8 +197,9 @@
</activity>
<activity
android:name=".ui.EasterEggMonke"
android:exported="true" />
android:name=".ui.EasterEggMonkeActivity"
android:exported="false"
android:noHistory="true" />
<receiver
android:name=".receivers.VideoDownloadRestartReceiver"

View File

@ -102,7 +102,6 @@ import com.lagradost.cloudstream3.ui.APIRepository
import com.lagradost.cloudstream3.ui.SyncWatchType
import com.lagradost.cloudstream3.ui.WatchType
import com.lagradost.cloudstream3.ui.account.AccountHelper.showAccountSelectLinear
import com.lagradost.cloudstream3.ui.account.AccountViewModel
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
import com.lagradost.cloudstream3.ui.home.HomeViewModel
import com.lagradost.cloudstream3.ui.library.LibraryViewModel
@ -685,7 +684,18 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
private fun NavDestination.matchDestination(@IdRes destId: Int): Boolean =
hierarchy.any { it.id == destId }
private var lastNavTime = 0L
private fun onNavDestinationSelected(item: MenuItem, navController: NavController): Boolean {
val currentTime = System.currentTimeMillis()
// safeDebounce: Check if a previous tap happened within the last 400ms
if (currentTime - lastNavTime < 400) return false
lastNavTime = currentTime
val destinationId = item.itemId
// Check if we are already at the selected destination
if(navController.currentDestination?.id == destinationId) return false
val builder = NavOptions.Builder().setLaunchSingleTop(true).setRestoreState(true)
.setEnterAnim(R.anim.enter_anim)
.setExitAnim(R.anim.exit_anim)
@ -698,11 +708,11 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
saveState = true
)
}
val options = builder.build()
return try {
navController.navigate(item.itemId, null, options)
navController.currentDestination?.matchDestination(item.itemId) == true
navController.navigate(destinationId, null, builder.build())
navController.currentDestination?.matchDestination(destinationId) == true
} catch (e: IllegalArgumentException) {
Log.e("NavigationError", "Failed to navigate: ${e.message}")
false
}
}
@ -742,7 +752,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
lateinit var viewModel: ResultViewModel2
lateinit var syncViewModel: SyncViewModel
private var libraryViewModel: LibraryViewModel? = null
private var accountViewModel: AccountViewModel? = null
/** kinda dirty, however it signals that we should use the watch status as sync or not*/
var isLocalList: Boolean = false

View File

@ -12,13 +12,13 @@ import android.view.View
import android.view.animation.AccelerateInterpolator
import android.view.animation.LinearInterpolator
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.activity.ComponentActivity
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.view.isVisible
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.databinding.ActivityEasterEggMonkeBinding
class EasterEggMonke : AppCompatActivity() {
class EasterEggMonkeActivity : ComponentActivity() {
lateinit var binding : ActivityEasterEggMonkeBinding
override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -3,7 +3,7 @@ package com.lagradost.cloudstream3.ui.account
import android.app.Activity
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.view.LayoutInflater
import android.view.inputmethod.EditorInfo
@ -31,6 +31,7 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper
import com.lagradost.cloudstream3.utils.DataStoreHelper.getDefaultAccount
import com.lagradost.cloudstream3.utils.ImageLoader.loadImage
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
import com.lagradost.cloudstream3.utils.UIHelper.navigate
import com.lagradost.cloudstream3.utils.UIHelper.showInputMethod
object AccountHelper {
@ -217,7 +218,7 @@ object AccountHelper {
val activity = context.getActivity()
if (activity is AccountSelectActivity) {
isPinValid = true
activity.viewModel.handleAccountSelect(getDefaultAccount(context), activity)
activity.accountViewModel.handleAccountSelect(getDefaultAccount(context), activity)
}
}
}
@ -307,9 +308,10 @@ object AccountHelper {
builder.show()
binding.manageAccountsButton.setOnClickListener {
val accountSelectIntent = Intent(activity, AccountSelectActivity::class.java)
accountSelectIntent.putExtra("isEditingFromMainActivity", true)
activity.startActivity(accountSelectIntent)
activity.navigate(
R.id.accountSelectActivity,
Bundle().apply { putBoolean("isEditingFromMainActivity", true) }
)
builder.dismissSafe()
}

View File

@ -1,11 +1,10 @@
package com.lagradost.cloudstream3.ui.account
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import androidx.activity.ComponentActivity
import androidx.activity.viewModels
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager
import com.lagradost.cloudstream3.CommonActivity
@ -33,10 +32,11 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.accounts
import com.lagradost.cloudstream3.utils.DataStoreHelper.selectedKeyIndex
import com.lagradost.cloudstream3.utils.DataStoreHelper.setAccount
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.utils.UIHelper.openActivity
class AccountSelectActivity : AppCompatActivity(), BiometricCallback {
class AccountSelectActivity : ComponentActivity(), BiometricCallback {
lateinit var viewModel: AccountViewModel
val accountViewModel: AccountViewModel by viewModels()
@SuppressLint("NotifyDataSetChanged")
override fun onCreate(savedInstanceState: Bundle?) {
@ -56,8 +56,6 @@ class AccountSelectActivity : AppCompatActivity(), BiometricCallback {
val skipStartup = settingsManager.getBoolean(getString(R.string.skip_startup_account_select_key), false
) || accounts.count() <= 1
viewModel = ViewModelProvider(this)[AccountViewModel::class.java]
fun askBiometricAuth() {
if (isLayout(PHONE) && isAuthEnabled(this)) {
@ -75,7 +73,7 @@ class AccountSelectActivity : AppCompatActivity(), BiometricCallback {
}
}
observe(viewModel.isAllowedLogin) { isAllowedLogin ->
observe(accountViewModel.isAllowedLogin) { isAllowedLogin ->
if (isAllowedLogin) {
// We are allowed to continue to MainActivity
navigateToMainActivity()
@ -88,7 +86,7 @@ class AccountSelectActivity : AppCompatActivity(), BiometricCallback {
val currentAccount = accounts.firstOrNull { it.keyIndex == selectedKeyIndex }
if (currentAccount?.lockPin != null) {
CommonActivity.init(this)
viewModel.handleAccountSelect(currentAccount, this, true)
accountViewModel.handleAccountSelect(currentAccount, this, true)
} else {
if (accounts.count() > 1) {
showToast(this, getString(
@ -110,16 +108,16 @@ class AccountSelectActivity : AppCompatActivity(), BiometricCallback {
val recyclerView: AutofitRecyclerView = binding.accountRecyclerView
observe(viewModel.accounts) { liveAccounts ->
observe(accountViewModel.accounts) { liveAccounts ->
val adapter = AccountAdapter(
liveAccounts,
// Handle the selected account
accountSelectCallback = {
viewModel.handleAccountSelect(it, this)
accountViewModel.handleAccountSelect(it, this)
},
accountCreateCallback = { viewModel.handleAccountUpdate(it, this) },
accountCreateCallback = { accountViewModel.handleAccountUpdate(it, this) },
accountEditCallback = {
viewModel.handleAccountUpdate(it, this)
accountViewModel.handleAccountUpdate(it, this)
// We came from MainActivity, return there
// and switch to the edited account
@ -128,7 +126,7 @@ class AccountSelectActivity : AppCompatActivity(), BiometricCallback {
navigateToMainActivity()
}
},
accountDeleteCallback = { viewModel.handleAccountDelete(it,this) }
accountDeleteCallback = { accountViewModel.handleAccountDelete(it,this) }
)
recyclerView.adapter = adapter
@ -139,13 +137,13 @@ class AccountSelectActivity : AppCompatActivity(), BiometricCallback {
)
}
observe(viewModel.selectedKeyIndex) { selectedKeyIndex ->
observe(accountViewModel.selectedKeyIndex) { selectedKeyIndex ->
// Scroll to current account (which is focused by default)
val layoutManager = recyclerView.layoutManager as GridLayoutManager
layoutManager.scrollToPositionWithOffset(selectedKeyIndex, 0)
}
observe(viewModel.isEditing) { isEditing ->
observe(accountViewModel.isEditing) { isEditing ->
if (isEditing) {
binding.editAccountButton.setImageResource(R.drawable.ic_baseline_close_24)
binding.title.setText(R.string.manage_accounts)
@ -160,7 +158,7 @@ class AccountSelectActivity : AppCompatActivity(), BiometricCallback {
}
if (isEditingFromMainActivity) {
viewModel.setIsEditing(true)
accountViewModel.setIsEditing(true)
}
binding.editAccountButton.setOnClickListener {
@ -171,7 +169,7 @@ class AccountSelectActivity : AppCompatActivity(), BiometricCallback {
return@setOnClickListener
}
viewModel.toggleIsEditing()
accountViewModel.toggleIsEditing()
}
if (isLayout(TV or EMULATOR)) {
@ -185,8 +183,7 @@ class AccountSelectActivity : AppCompatActivity(), BiometricCallback {
}
private fun navigateToMainActivity() {
val mainIntent = Intent(this, MainActivity::class.java)
startActivity(mainIntent)
openActivity(MainActivity::class.java)
finish() // Finish the account selection activity
}

View File

@ -1,7 +1,6 @@
package com.lagradost.cloudstream3.ui.settings
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
@ -25,7 +24,6 @@ import com.lagradost.cloudstream3.databinding.AddSiteInputBinding
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.network.initClient
import com.lagradost.cloudstream3.ui.EasterEggMonke
import com.lagradost.cloudstream3.ui.settings.Globals.EMULATOR
import com.lagradost.cloudstream3.ui.settings.Globals.TV
import com.lagradost.cloudstream3.ui.settings.Globals.beneneCount
@ -43,6 +41,7 @@ import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog
import com.lagradost.cloudstream3.utils.SubtitleHelper
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.utils.UIHelper.navigate
import com.lagradost.cloudstream3.utils.USER_PROVIDER_API
import com.lagradost.cloudstream3.utils.VideoDownloadManager
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath
@ -392,16 +391,13 @@ class SettingsGeneral : PreferenceFragmentCompat() {
try {
beneneCount++
if (beneneCount%20 == 0) {
val intent = Intent(context, EasterEggMonke::class.java)
startActivity(intent)
activity?.navigate(R.id.easterEggMonkeActivity)
}
settingsManager.edit().putInt(
getString(R.string.benene_count),
beneneCount
)
.apply()
it.summary =
getString(R.string.benene_count_text).format(beneneCount)
).apply()
it.summary = getString(R.string.benene_count_text).format(beneneCount)
} catch (e: Exception) {
logError(e)
}

View File

@ -3,7 +3,6 @@ package com.lagradost.cloudstream3.utils
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build.VERSION.SDK_INT
import android.util.Log
import android.widget.ImageView
import androidx.annotation.DrawableRes
@ -54,7 +53,7 @@ object ImageLoader {
DiskCache.Builder()
.directory(context.cacheDir.resolve("cs3_image_cache").toOkioPath())
.maxSizeBytes(256 * 1024 * 1024) // 256 MB
.maxSizePercent(0.04) // Use 4% of the device's storage space for disk caching
.maxSizePercent(0.04) // Use 4 % of the device's storage space for disk caching
.build()
}
.diskCachePolicy(CachePolicy.ENABLED)

View File

@ -8,6 +8,7 @@ import android.app.Dialog
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.content.res.Resources
@ -15,8 +16,6 @@ import android.graphics.Bitmap
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.TransactionTooLargeException
import android.util.Log
import android.view.Gravity
@ -32,7 +31,6 @@ import android.widget.ListView
import android.widget.Toast.LENGTH_LONG
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.annotation.IdRes
import androidx.annotation.StyleRes
import androidx.appcompat.view.ContextThemeWrapper
import androidx.appcompat.view.menu.MenuBuilder
@ -51,6 +49,7 @@ import androidx.core.view.marginTop
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.navigation.NavOptions
import androidx.navigation.fragment.NavHostFragment
import androidx.palette.graphics.Palette
import androidx.preference.PreferenceManager
@ -59,6 +58,7 @@ import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipDrawable
import com.google.android.material.chip.ChipGroup
import com.lagradost.cloudstream3.AcraApplication.Companion.context
import com.lagradost.cloudstream3.CommonActivity
import com.lagradost.cloudstream3.CommonActivity.activity
import com.lagradost.cloudstream3.CommonActivity.showToast
import com.lagradost.cloudstream3.R
@ -66,6 +66,9 @@ import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.ui.settings.Globals
import com.lagradost.cloudstream3.ui.settings.Globals.EMULATOR
import com.lagradost.cloudstream3.ui.settings.Globals.isLayout
import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.UIHelper.navigate
import kotlinx.coroutines.delay
import kotlin.math.roundToInt
object UIHelper {
@ -216,17 +219,65 @@ object UIHelper {
}
}
fun Activity?.navigate(@IdRes navigation: Int, arguments: Bundle? = null) {
try {
if (this is FragmentActivity) {
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as? NavHostFragment?
navHostFragment?.navController?.navigate(navigation, arguments)
fun Activity?.navigate(
navigationId: Int,
args: Bundle? = null,
navOptions: NavOptions? = null // To control nav graph & manage back stack
) {
val tag = "NavComponent"
if (this is FragmentActivity) {
try {
runOnUiThread {
// Navigate using navigation ID
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as? NavHostFragment
Log.i(tag, "Navigating to fragment: $navigationId")
navHostFragment?.navController?.navigate(navigationId, args, navOptions)
}
} catch (t: Throwable) {
logError(t)
}
}
}
// Open activities from an activity outside the nav graph
fun Context.openActivity(activity: Class<*>, args: Bundle? = null) {
val tag = "NavComponent"
try {
val intent = Intent(this, activity)
if (args != null) {
intent.putExtras(args)
}
Log.i(tag, "Navigating to Activity: ${activity.simpleName}")
startActivity(intent)
} catch (t: Throwable) {
logError(t)
}
}
fun FragmentActivity.popCurrentPage() {
// Use the main looper handler to post actions on the main thread
main {
// Post the back press action to the main thread handler to ensure it executes
// after any currently pending UI updates or fragment transactions.
if (!supportFragmentManager.isStateSaved) {
// Get the top fragment from the back stack
Log.d("popFragment", "Destroying Fragment")
// If the state is not saved, it's safe to perform the back press action.
onBackPressedDispatcher.onBackPressed()
} else {
// If the state is saved, retry the back press action after a slight delay.
// This gives the FragmentManager time to complete any ongoing state-saving
// operations or transactions, ensuring that we do not encounter an IllegalStateException.
delay(100)
if (!supportFragmentManager.isStateSaved) {
Log.d("popFragment", "Destroying after delay")
onBackPressedDispatcher.onBackPressed()
}
}
}
}
@ColorInt
fun Context.getResourceColor(@AttrRes resource: Int, alphaFactor: Float = 1f): Int {
val typedArray = obtainStyledAttributes(intArrayOf(resource))
@ -299,26 +350,6 @@ object UIHelper {
//}
}
fun FragmentActivity.popCurrentPage() {
// Post the back press action to the main thread handler to ensure it executes
// after any currently pending UI updates or fragment transactions.
Handler(Looper.getMainLooper()).post {
// Check if the FragmentManager state is saved. If it is, we cannot perform
// fragment transactions safely because the state may be inconsistent.
if (!supportFragmentManager.isStateSaved) {
// If the state is not saved, it's safe to perform the back press action.
this.onBackPressedDispatcher.onBackPressed()
} else {
// If the state is saved, retry the back press action after a slight delay.
// This gives the FragmentManager time to complete any ongoing state-saving
// operations or transactions, ensuring that we do not encounter an IllegalStateException.
Handler(Looper.getMainLooper()).postDelayed({
this.onBackPressedDispatcher.onBackPressed()
}, 100)
}
}
}
fun Context.getStatusBarHeight(): Int {
if (isLayout(Globals.TV or EMULATOR)) {
return 0

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:interpolator="@android:anim/linear_interpolator"
android:duration="@integer/config_navAnimTime"
android:fromAlpha="0.0"
android:toAlpha="1.0"/>
</set>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:interpolator="@android:anim/linear_interpolator"
android:duration="@integer/config_navAnimTime"
android:fromAlpha="1.0"
android:toAlpha="0.0"/>
</set>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:interpolator="@android:anim/linear_interpolator"
android:duration="@integer/config_navAnimTime"
android:fromAlpha="0.0"
android:toAlpha="1.0"/>
</set>

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:interpolator="@android:anim/linear_interpolator"
android:duration="@integer/config_navAnimTime"
android:fromAlpha="1.0"
android:toAlpha="0.0"/>
</set>

View File

@ -661,4 +661,17 @@
app:popEnterAnim="@anim/enter_anim"
app:popExitAnim="@anim/exit_anim"
tools:layout="@layout/fragment_setup_media" />
<activity
android:id="@+id/accountSelectActivity"
android:name="com.lagradost.cloudstream3.ui.account.AccountSelectActivity"
android:label="AccountSelectActivity"
tools:layout="@layout/activity_account_select" />
<activity
android:id="@+id/easterEggMonkeActivity"
android:name="com.lagradost.cloudstream3.ui.EasterEggMonkeActivity"
android:label="EasterEggMonkeActivity"
tools:layout="@layout/activity_easter_egg_monke" />
</navigation>

View File

@ -202,4 +202,4 @@ suspend fun <T> safeApiCall(
throwAbleToResource(throwable)
}
}
}
}