mirror of
https://github.com/recloudstream/cloudstream.git
synced 2025-05-17 11:15:54 +08:00
154
.github/workflows/build_to_archive.yml
vendored
154
.github/workflows/build_to_archive.yml
vendored
@ -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
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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?) {
|
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
||||
|
@ -202,4 +202,4 @@ suspend fun <T> safeApiCall(
|
||||
throwAbleToResource(throwable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user