From d5b422da01ef95b5d14758af3dff3509a4c12c65 Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Fri, 3 Nov 2023 18:56:40 -0600 Subject: [PATCH] Use a ViewModel for live updates --- .../lagradost/cloudstream3/MainActivity.kt | 7 + .../cloudstream3/ui/account/AccountAdapter.kt | 16 ++- .../cloudstream3/ui/account/AccountHelper.kt | 61 +++++---- .../ui/account/AccountSelectActivity.kt | 121 +++++++++++------- .../ui/account/AccountViewModel.kt | 21 +++ .../cloudstream3/ui/home/HomeFragment.kt | 4 +- .../ui/home/HomeParentItemAdapterPreview.kt | 3 +- 7 files changed, 153 insertions(+), 80 deletions(-) create mode 100644 app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountViewModel.kt diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index a41028bd..eede0f8d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -92,6 +92,8 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStri import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.inAppAuths import com.lagradost.cloudstream3.ui.APIRepository import com.lagradost.cloudstream3.ui.WatchType +import com.lagradost.cloudstream3.ui.account.AccountHelper +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.player.BasicLink @@ -1610,4 +1612,9 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { false } } + + fun showAccountSelectLinear(context: Context) { + val viewModel = ViewModelProvider(this)[AccountViewModel::class.java] + AccountHelper.showAccountSelectLinear(context, viewModel, this) + } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountAdapter.kt index 32edf561..ebd3e2cb 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountAdapter.kt @@ -22,7 +22,8 @@ class AccountAdapter( private val accounts: List, private val accountSelectCallback: (DataStoreHelper.Account) -> Unit, private val accountCreateCallback: (DataStoreHelper.Account) -> Unit, - private val accountEditCallback: (DataStoreHelper.Account) -> Unit + private val accountEditCallback: (DataStoreHelper.Account) -> Unit, + private val accountDeleteCallback: () -> Unit ) : RecyclerView.Adapter() { companion object { @@ -62,8 +63,11 @@ class AccountAdapter( } else { root.setOnLongClickListener { showAccountEditDialog(root.context, account, isNewAccount = false) { - accountEditCallback.invoke(it) + if (it != null) { + accountEditCallback.invoke(it) + } else accountDeleteCallback.invoke() } + true } } @@ -105,7 +109,9 @@ class AccountAdapter( root.setOnClickListener { showAccountEditDialog(root.context, account, isNewAccount = false) { - accountEditCallback.invoke(it) + if (it != null) { + accountEditCallback.invoke(it) + } else accountDeleteCallback.invoke() } } } @@ -128,7 +134,9 @@ class AccountAdapter( customImage = null, defaultImageIndex = image ), isNewAccount = true) { - accountCreateCallback.invoke(it) + if (it != null) { + accountCreateCallback.invoke(it) + } } } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountHelper.kt index 0b28595c..d41bac9b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountHelper.kt @@ -12,6 +12,7 @@ import androidx.appcompat.app.AlertDialog import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged +import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.RecyclerView import com.google.android.material.bottomsheet.BottomSheetDialog import com.lagradost.cloudstream3.AcraApplication.Companion.removeKeys @@ -20,6 +21,7 @@ import com.lagradost.cloudstream3.databinding.AccountEditDialogBinding import com.lagradost.cloudstream3.databinding.AccountSelectLinearBinding import com.lagradost.cloudstream3.databinding.LockPinDialogBinding import com.lagradost.cloudstream3.mvvm.logError +import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.ui.result.setImage import com.lagradost.cloudstream3.ui.result.setLinearListLayout import com.lagradost.cloudstream3.utils.AppUtils.setDefaultFocus @@ -35,7 +37,7 @@ object AccountHelper { context: Context, account: DataStoreHelper.Account, isNewAccount: Boolean, - callback: (DataStoreHelper.Account) -> Unit + callback: (DataStoreHelper.Account?) -> Unit ) { val binding = AccountEditDialogBinding.inflate(LayoutInflater.from(context), null, false) val builder = AlertDialog.Builder(context, R.style.AlertDialogCustom) @@ -65,6 +67,7 @@ object AccountHelper { // Update UI setAccount(getDefaultAccount(context), true) + callback.invoke(null) dialog?.dismissSafe() } @@ -274,7 +277,11 @@ object AccountHelper { }, 200) } - fun showAccountSelectLinear(context: Context) { + fun showAccountSelectLinear( + context: Context, + viewModel: AccountViewModel, + lifecycleOwner: LifecycleOwner + ) { fun onAccountUpdated(account: DataStoreHelper.Account) { val currentAccounts = DataStoreHelper.accounts.toMutableList() @@ -318,30 +325,38 @@ object AccountHelper { recyclerView.addItemDecoration(AccountSelectLinearItemDecoration(itemWidth, itemHeight)) recyclerView.setLinearListLayout(isHorizontal = true) - recyclerView.adapter = AccountAdapter( - getAccounts(context), - accountSelectCallback = { account -> - // Check if the selected account has a lock PIN set - if (account.lockPin != null) { - // Prompt for the lock pin - showPinInputDialog(context, account.lockPin, false) { pin -> - if (pin == null) return@showPinInputDialog - // Pin is correct, unlock the profile + + lifecycleOwner.observe(viewModel.accountsLiveData) { liveAccounts -> + recyclerView.adapter = AccountAdapter( + liveAccounts, + accountSelectCallback = { account -> + // Check if the selected account has a lock PIN set + if (account.lockPin != null) { + // Prompt for the lock pin + showPinInputDialog(context, account.lockPin, false) { pin -> + if (pin == null) return@showPinInputDialog + // Pin is correct, unlock the profile + setAccount(account, true) + builder.dismissSafe() + } + } else { + // No lock PIN set, directly set the account setAccount(account, true) builder.dismissSafe() } - } else { - // No lock PIN set, directly set the account - setAccount(account, true) - builder.dismissSafe() + }, + accountCreateCallback = { + onAccountUpdated(it) + viewModel.updateAccounts(getAccounts(context)) + }, + accountEditCallback = { + onAccountUpdated(it) + viewModel.updateAccounts(getAccounts(context)) + }, + accountDeleteCallback = { + viewModel.updateAccounts(getAccounts(context)) } - }, - accountCreateCallback = { - onAccountUpdated(it) - builder.dismissSafe() - }, - // Editing is done using AccountSelectActivity - accountEditCallback = {} - ) + ) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountSelectActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountSelectActivity.kt index fb7dff0c..46ff0fc5 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountSelectActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountSelectActivity.kt @@ -4,6 +4,7 @@ import android.content.Intent import android.os.Bundle import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import com.lagradost.cloudstream3.CommonActivity @@ -11,6 +12,7 @@ import com.lagradost.cloudstream3.CommonActivity.loadThemes import com.lagradost.cloudstream3.MainActivity import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.databinding.ActivityAccountSelectBinding +import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.ui.account.AccountAdapter.Companion.VIEW_TYPE_EDIT_ACCOUNT import com.lagradost.cloudstream3.ui.account.AccountAdapter.Companion.VIEW_TYPE_SELECT_ACCOUNT import com.lagradost.cloudstream3.ui.account.AccountHelper.showPinInputDialog @@ -23,11 +25,18 @@ class AccountSelectActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + + // Are we editing and coming from MainActivity? + val isEditingFromMainActivity = intent.getBooleanExtra( + "isEditingFromMainActivity", + false + ) + val accounts = getAccounts(this@AccountSelectActivity) // Don't show account selection if there is only // one account that exists - if (accounts.count() <= 1) { + if (!isEditingFromMainActivity && accounts.count() <= 1) { navigateToMainActivity() return } @@ -42,61 +51,77 @@ class AccountSelectActivity : AppCompatActivity() { val recyclerView: RecyclerView = binding.accountRecyclerView - // Are we editing and coming from MainActivity? - val isEditingFromMainActivity = intent.getBooleanExtra( - "isEditingFromMainActivity", - false - ) + val viewModel = ViewModelProvider(this)[AccountViewModel::class.java] - val adapter = AccountAdapter( - accounts, - // Handle the selected account - accountSelectCallback = { onAccountSelected(it) }, - accountCreateCallback = { onAccountUpdated(it) }, - accountEditCallback = { - onAccountUpdated(it) + observe(viewModel.accountsLiveData) { liveAccounts -> + val adapter = AccountAdapter( + liveAccounts, + // Handle the selected account + accountSelectCallback = { onAccountSelected(it) }, + accountCreateCallback = { + onAccountUpdated(it) - // We came from MainActivity, return there - // and switch to the edited account - if (isEditingFromMainActivity) { - DataStoreHelper.setAccount(it, it.keyIndex != DataStoreHelper.selectedKeyIndex) - navigateToMainActivity() + viewModel.updateAccounts( + getAccounts(binding.root.context) + ) + }, + accountEditCallback = { + onAccountUpdated(it) + + viewModel.updateAccounts( + getAccounts(binding.root.context) + ) + + // We came from MainActivity, return there + // and switch to the edited account + if (isEditingFromMainActivity) { + DataStoreHelper.setAccount( + it, + it.keyIndex != DataStoreHelper.selectedKeyIndex + ) + navigateToMainActivity() + } + }, + accountDeleteCallback = { + viewModel.updateAccounts( + getAccounts(binding.root.context) + ) } - } - ) + ) - recyclerView.adapter = adapter + recyclerView.adapter = adapter - var isEditing = false + var isEditing = false - if (isEditingFromMainActivity) { - binding.editAccountButton.setImageResource(R.drawable.ic_baseline_close_24) - binding.title.setText(R.string.manage_accounts) - adapter.viewType = VIEW_TYPE_EDIT_ACCOUNT - isEditing = true + if (isEditingFromMainActivity) { + binding.editAccountButton.setImageResource(R.drawable.ic_baseline_close_24) + binding.title.setText(R.string.manage_accounts) + adapter.viewType = VIEW_TYPE_EDIT_ACCOUNT + isEditing = true - adapter.notifyDataSetChanged() - } - - binding.editAccountButton.setOnClickListener { - isEditing = !isEditing - if (isEditing) { - (it as ImageView).setImageResource(R.drawable.ic_baseline_close_24) - binding.title.setText(R.string.manage_accounts) - adapter.viewType = VIEW_TYPE_EDIT_ACCOUNT - } else { - // We came from MainActivity, return there - // and resume it's state - if (isEditingFromMainActivity) { - navigateToMainActivity() - } - - (it as ImageView).setImageResource(R.drawable.ic_baseline_edit_24) - binding.title.setText(R.string.select_an_account) - adapter.viewType = VIEW_TYPE_SELECT_ACCOUNT + adapter.notifyDataSetChanged() } - adapter.notifyDataSetChanged() + binding.editAccountButton.setOnClickListener { + isEditing = !isEditing + if (isEditing) { + (it as ImageView).setImageResource(R.drawable.ic_baseline_close_24) + binding.title.setText(R.string.manage_accounts) + adapter.viewType = VIEW_TYPE_EDIT_ACCOUNT + } else { + // We came from MainActivity, return there + // and resume it's state + if (isEditingFromMainActivity) { + navigateToMainActivity() + } + + (it as ImageView).setImageResource(R.drawable.ic_baseline_edit_24) + binding.title.setText(R.string.select_an_account) + adapter.viewType = VIEW_TYPE_SELECT_ACCOUNT + } + + adapter.notifyDataSetChanged() + } } if (isTvSettings()) { @@ -137,8 +162,6 @@ class AccountSelectActivity : AppCompatActivity() { DataStoreHelper.accounts = currentAccounts.toTypedArray() DataStoreHelper.currentHomePage = currentHomePage - - this.recreate() } private fun setAccount(account: DataStoreHelper.Account) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountViewModel.kt new file mode 100644 index 00000000..2a8ee97d --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountViewModel.kt @@ -0,0 +1,21 @@ +package com.lagradost.cloudstream3.ui.account + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.lagradost.cloudstream3.utils.DataStoreHelper + +class AccountViewModel : ViewModel() { + private val _accountsLiveData = MutableLiveData>() + val accountsLiveData: LiveData> get() = _accountsLiveData + + init { + // Default to using the getAccounts function to retrieve initial data + val initialAccounts = DataStoreHelper.accounts.toList() + _accountsLiveData.value = initialAccounts + } + + fun updateAccounts(newAccounts: List) { + _accountsLiveData.value = newAccounts + } +} 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 a13f2944..f17cce8b 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 @@ -38,7 +38,6 @@ import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.mvvm.observeNullable import com.lagradost.cloudstream3.ui.APIRepository.Companion.noneApi import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi -import com.lagradost.cloudstream3.ui.account.AccountHelper.showAccountSelectLinear import com.lagradost.cloudstream3.ui.result.txt import com.lagradost.cloudstream3.ui.search.* import com.lagradost.cloudstream3.ui.search.SearchHelper.handleSearchClickCallback @@ -497,8 +496,9 @@ class HomeFragment : Fragment() { homeApiFab.setOnClickListener(apiChangeClickListener) homeChangeApi.setOnClickListener(apiChangeClickListener) homeSwitchAccount.setOnClickListener { v -> - showAccountSelectLinear(v?.context ?: return@setOnClickListener) + (CommonActivity.activity as MainActivity).showAccountSelectLinear(v?.context ?: return@setOnClickListener) } + homeRandom.setOnClickListener { if (listHomepageItems.isNotEmpty()) { activity.loadSearchResult(listHomepageItems.random()) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapterPreview.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapterPreview.kt index 2616c92a..1caa9a47 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapterPreview.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapterPreview.kt @@ -27,7 +27,6 @@ import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.debugException import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.ui.WatchType -import com.lagradost.cloudstream3.ui.account.AccountHelper.showAccountSelectLinear import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.selectHomepage import com.lagradost.cloudstream3.ui.result.FOCUS_SELF import com.lagradost.cloudstream3.ui.result.ResultViewModel2 @@ -479,7 +478,7 @@ class HomeParentItemAdapterPreview( } homeAccount?.setOnClickListener { v -> - showAccountSelectLinear(v?.context ?: return@setOnClickListener) + (activity as MainActivity).showAccountSelectLinear(v?.context ?: return@setOnClickListener) } (binding as? FragmentHomeHeadTvBinding)?.apply {