diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b98372491..3f4ca64d5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -218,10 +218,6 @@ android:name=".page.receive.ReceiveActivity" android:screenOrientation="portrait"/> - - @@ -253,10 +249,6 @@ android:name=".page.token.detail.TokenDetailActivity" android:screenOrientation="portrait"/> - - finish() - else -> super.onOptionsItemSelected(item) - } - return true - } - - companion object { - fun launch(context: Context) { - context.startActivity(Intent(context, NftCollectionListActivity::class.java)) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/NftCollectionListViewModel.kt b/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/NftCollectionListViewModel.kt deleted file mode 100644 index 180e7823d..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/NftCollectionListViewModel.kt +++ /dev/null @@ -1,111 +0,0 @@ -package com.flowfoundation.wallet.page.nft.collectionlist - -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import com.google.gson.Gson -import com.flowfoundation.wallet.R -import com.flowfoundation.wallet.manager.config.NftCollection -import com.flowfoundation.wallet.manager.config.NftCollectionConfig -import com.flowfoundation.wallet.manager.flowjvm.cadenceNftEnabled -import com.flowfoundation.wallet.manager.nft.NftCollectionStateChangeListener -import com.flowfoundation.wallet.manager.nft.NftCollectionStateManager -import com.flowfoundation.wallet.manager.transaction.OnTransactionStateChange -import com.flowfoundation.wallet.manager.transaction.TransactionState -import com.flowfoundation.wallet.manager.transaction.TransactionStateManager -import com.flowfoundation.wallet.page.nft.collectionlist.model.NftCollectionItem -import com.flowfoundation.wallet.page.window.bubble.tools.pushBubbleStack -import com.flowfoundation.wallet.utils.ioScope -import com.flowfoundation.wallet.utils.toast -import com.flowfoundation.wallet.utils.viewModelIOScope -import org.onflow.flow.models.TransactionStatus - -class NftCollectionListViewModel : ViewModel(), OnTransactionStateChange, NftCollectionStateChangeListener { - - val collectionListLiveData = MutableLiveData>() - var cadenceExecuteLiveData = MutableLiveData() - - private val collectionList = mutableListOf() - - private var transactionIds = mutableListOf() - - private var keyword = "" - - init { - TransactionStateManager.addOnTransactionStateChange(this) - NftCollectionStateManager.addListener(this) - } - - fun load() { - viewModelIOScope(this) { - collectionList.clear() - collectionList.addAll( - NftCollectionConfig.list() - .filter { it.contractId().isNotEmpty() } - .map { NftCollectionItem(collection = it, isAdded = NftCollectionStateManager.isTokenAdded(it.contractId()), isAdding = false) }) - collectionListLiveData.postValue(collectionList.toList()) - - onTransactionStateChange() - - NftCollectionStateManager.fetchState() - } - } - - fun search(keyword: String) { - this.keyword = keyword - if (keyword.isBlank()) { - collectionListLiveData.postValue(collectionList.toList()) - } else { - collectionListLiveData.postValue(collectionList.filter { it.collection.name.lowercase().contains(keyword.lowercase()) }) - } - } - - fun clearSearch() { - this.keyword = "" - search("") - } - - fun addToken(collection: NftCollection) { - ioScope { - val transactionId = cadenceNftEnabled(collection) - if (transactionId.isNullOrBlank()) { - toast(msgRes = R.string.add_token_failed) - } else { - val transactionState = TransactionState( - transactionId = transactionId, - time = System.currentTimeMillis(), - state = TransactionStatus.PENDING.ordinal, - type = TransactionState.TYPE_ENABLE_NFT, - data = Gson().toJson(collection) - ) - TransactionStateManager.newTransaction(transactionState) - pushBubbleStack(transactionState) - transactionIds.add(transactionId) - onTransactionStateChange() - } - cadenceExecuteLiveData.postValue(true) - } - } - - override fun onTransactionStateChange() { - viewModelIOScope(this) { - val transactionList = TransactionStateManager.getTransactionStateList() - transactionList.forEach { state -> - if (state.type == TransactionState.TYPE_ENABLE_NFT) { - val coin = state.nftCollectionData() - val index = collectionList.indexOfFirst { it.collection.contractId() == coin.contractId() } - val isAdded = NftCollectionStateManager.isTokenAdded(coin.contractId()) || state.isSuccess() - collectionList[index] = NftCollectionItem( - collection = collectionList[index].collection, - isAdding = state.isProcessing() && !isAdded, - isAdded = isAdded, - ) - } - } - search(keyword) - } - } - - override fun onNftCollectionStateChange(collection: NftCollection, isEnable: Boolean) { - onTransactionStateChange() - } -} diff --git a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/NftEnableConfirmDialog.kt b/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/NftEnableConfirmDialog.kt deleted file mode 100644 index 6a60919ab..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/NftEnableConfirmDialog.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.flowfoundation.wallet.page.nft.collectionlist - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.FragmentManager -import androidx.lifecycle.ViewModelProvider -import com.bumptech.glide.Glide -import com.google.android.material.bottomsheet.BottomSheetDialogFragment -import com.flowfoundation.wallet.databinding.DialogAddCollectionConfirmBinding -import com.flowfoundation.wallet.manager.config.NftCollection -import com.flowfoundation.wallet.utils.uiScope -import jp.wasabeef.glide.transformations.BlurTransformation - -class NftEnableConfirmDialog : BottomSheetDialogFragment() { - - private val collection by lazy { arguments?.getParcelable(EXTRA_TOKEN)!! } - - private lateinit var binding: DialogAddCollectionConfirmBinding - - private lateinit var viewModel: NftCollectionListViewModel - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - binding = DialogAddCollectionConfirmBinding.inflate(inflater) - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - viewModel = ViewModelProvider(requireActivity())[NftCollectionListViewModel::class.java].apply { - cadenceExecuteLiveData.observe(this@NftEnableConfirmDialog) { - if (it) { - dismiss() - cadenceExecuteLiveData.value = false - } - } - } - - binding.closeButton.setOnClickListener { dismiss() } - with(binding) { - nameView.text = collection.name - descView.text = collection.description ?: "" - Glide.with(coverView).load(collection.banner()).transform(BlurTransformation(2, 5)).into(coverView) - actionButton.setOnClickListener { - uiScope { - actionButton.setProgressVisible(true) - viewModel.addToken(collection) - } - } - } - } - - companion object { - private const val EXTRA_TOKEN = "extra_token" - - fun show(fragmentManager: FragmentManager, collection: NftCollection) { - NftEnableConfirmDialog().apply { - arguments = Bundle().apply { - putParcelable(EXTRA_TOKEN, collection) - } - }.show(fragmentManager, "") - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/Utils.kt b/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/Utils.kt deleted file mode 100644 index 545ab70e7..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/Utils.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.flowfoundation.wallet.page.nft.collectionlist - -import android.annotation.SuppressLint -import androidx.recyclerview.widget.DiffUtil -import com.flowfoundation.wallet.page.address.model.AddressBookPersonModel - -val nftCollectionListDiffCallback = object : DiffUtil.ItemCallback() { - override fun areItemsTheSame(oldItem: Any, newItem: Any): Boolean { - if (oldItem is AddressBookPersonModel && newItem is AddressBookPersonModel) { - return oldItem.data == newItem.data - } - return oldItem == newItem - } - - @SuppressLint("DiffUtilEquals") - override fun areContentsTheSame(oldItem: Any, newItem: Any): Boolean { - if (oldItem is AddressBookPersonModel && newItem is AddressBookPersonModel) { - return oldItem.data == newItem.data && oldItem.isFriend == newItem.isFriend - } - return oldItem == newItem - } -} diff --git a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/adapter/NftCollectionListAdapter.kt b/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/adapter/NftCollectionListAdapter.kt deleted file mode 100644 index b9ebe88aa..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/adapter/NftCollectionListAdapter.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.flowfoundation.wallet.page.nft.collectionlist.adapter - -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import com.flowfoundation.wallet.R -import com.flowfoundation.wallet.base.recyclerview.BaseAdapter -import com.flowfoundation.wallet.base.recyclerview.BaseViewHolder -import com.flowfoundation.wallet.page.nft.collectionlist.model.NftCollectionItem -import com.flowfoundation.wallet.page.nft.collectionlist.nftCollectionListDiffCallback -import com.flowfoundation.wallet.page.nft.collectionlist.presenter.NftCollectionItemPresenter - -class NftCollectionListAdapter : BaseAdapter(nftCollectionListDiffCallback) { - - override fun getItemViewType(position: Int): Int { - return TYPE_TOKEN - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - return when (viewType) { - TYPE_TOKEN -> NftCollectionItemPresenter(parent.inflate(R.layout.item_nft_collection_list)) - else -> BaseViewHolder(View(parent.context)) - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is NftCollectionItemPresenter -> holder.bind(getItem(position) as NftCollectionItem) - } - } - - companion object { - private const val TYPE_TOKEN = 1 - } -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/model/NftCollectionItem.kt b/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/model/NftCollectionItem.kt deleted file mode 100644 index 7b891a6fb..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/model/NftCollectionItem.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.flowfoundation.wallet.page.nft.collectionlist.model - -import com.flowfoundation.wallet.manager.config.NftCollection -import com.google.gson.annotations.SerializedName - -data class NftCollectionItem( - @SerializedName("collection") - val collection: NftCollection, - @SerializedName("isAdded") - var isAdded: Boolean, - @SerializedName("isAdding") - var isAdding: Boolean? = null, -) { - fun isNormalState() = !(isAdded || isAdding == true) -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/model/NftCollectionListModel.kt b/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/model/NftCollectionListModel.kt deleted file mode 100644 index d489d728d..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/model/NftCollectionListModel.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.flowfoundation.wallet.page.nft.collectionlist.model - -class NftCollectionListModel( - val data: List? = null, -) \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/presenter/NftCollectionItemPresenter.kt b/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/presenter/NftCollectionItemPresenter.kt deleted file mode 100644 index 8275270ec..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/presenter/NftCollectionItemPresenter.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.flowfoundation.wallet.page.nft.collectionlist.presenter - -import android.view.View -import androidx.fragment.app.FragmentActivity -import com.bumptech.glide.Glide -import com.flowfoundation.wallet.R -import com.flowfoundation.wallet.base.presenter.BasePresenter -import com.flowfoundation.wallet.base.recyclerview.BaseViewHolder -import com.flowfoundation.wallet.databinding.ItemNftCollectionListBinding -import com.flowfoundation.wallet.manager.config.AppConfig -import com.flowfoundation.wallet.page.browser.openBrowser -import com.flowfoundation.wallet.page.nft.collectionlist.NftEnableConfirmDialog -import com.flowfoundation.wallet.page.nft.collectionlist.model.NftCollectionItem -import com.flowfoundation.wallet.utils.extensions.setVisible -import com.flowfoundation.wallet.utils.findActivity -import jp.wasabeef.glide.transformations.BlurTransformation - -class NftCollectionItemPresenter( - private val view: View, -) : BaseViewHolder(view), BasePresenter { - - private val binding by lazy { ItemNftCollectionListBinding.bind(view) } - - override fun bind(model: NftCollectionItem) { - with(binding) { - nameView.text = model.collection.name - descView.text = model.collection.description ?: "" - Glide.with(coverView).load(model.collection.banner()).transform(BlurTransformation(2, 5)).into(coverView) - stateButton.setOnClickListener { - if (model.isNormalState()) { - NftEnableConfirmDialog.show((findActivity(view) as FragmentActivity).supportFragmentManager, model.collection) - } - } - progressBar.setVisible(model.isAdding == true) - stateButton.setVisible(model.isAdding != true) - titleWrapper.setOnClickListener { - if (AppConfig.useInAppBrowser()) { - openBrowser(findActivity(view)!!, model.collection.officialWebsite) - } - } - stateButton.setImageResource(if (model.isNormalState()) R.drawable.ic_baseline_add_24_salmon_primary else R.drawable.ic_check_round) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/presenter/NftCollectionListPresenter.kt b/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/presenter/NftCollectionListPresenter.kt deleted file mode 100644 index c09ef7819..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/nft/collectionlist/presenter/NftCollectionListPresenter.kt +++ /dev/null @@ -1,94 +0,0 @@ -package com.flowfoundation.wallet.page.nft.collectionlist.presenter - -import android.graphics.Color -import android.transition.Scene -import android.transition.Slide -import android.transition.TransitionManager -import android.view.Gravity -import android.view.View -import android.view.ViewGroup -import android.view.inputmethod.EditorInfo -import androidx.core.widget.doOnTextChanged -import androidx.lifecycle.ViewModelProvider -import androidx.recyclerview.widget.LinearLayoutManager -import com.flowfoundation.wallet.R -import com.flowfoundation.wallet.base.presenter.BasePresenter -import com.flowfoundation.wallet.databinding.ActivityNftCollectionListBinding -import com.flowfoundation.wallet.page.nft.collectionlist.NftCollectionListActivity -import com.flowfoundation.wallet.page.nft.collectionlist.NftCollectionListViewModel -import com.flowfoundation.wallet.page.nft.collectionlist.adapter.NftCollectionListAdapter -import com.flowfoundation.wallet.page.nft.collectionlist.model.NftCollectionListModel -import com.flowfoundation.wallet.utils.extensions.* -import com.flowfoundation.wallet.widgets.itemdecoration.ColorDividerItemDecoration - -class NftCollectionListPresenter( - private val activity: NftCollectionListActivity, - private val binding: ActivityNftCollectionListBinding, -) : BasePresenter { - - private val viewModel by lazy { ViewModelProvider(activity)[NftCollectionListViewModel::class.java] } - private val adapter by lazy { NftCollectionListAdapter() } - - init { - setupToolbar() - setupEditText() - setupRecyclerView() - } - - override fun bind(model: NftCollectionListModel) { - model.data?.let { adapter.setNewDiffData(it) } - } - - private fun setupRecyclerView() { - with(binding.recyclerView) { - adapter = this@NftCollectionListPresenter.adapter - layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) - addItemDecoration( - ColorDividerItemDecoration(Color.TRANSPARENT, 12.dp2px().toInt()) - ) - } - } - - private fun setupEditText() { - with(binding.editText) { - setOnEditorActionListener { _, actionId, _ -> - if (actionId == EditorInfo.IME_ACTION_SEARCH) { - hideKeyboard() - viewModel.search(text.toString().trim()) - clearFocus() - } - return@setOnEditorActionListener false - } - doOnTextChanged { text, _, _, _ -> - viewModel.search(text.toString().trim()) - } - onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus -> onSearchFocusChange(hasFocus) } - } - - binding.cancelButton.setOnClickListener { - onSearchFocusChange(false) - binding.editText.hideKeyboard() - binding.editText.setText("") - binding.editText.clearFocus() - viewModel.clearSearch() - } - } - - private fun setupToolbar() { - binding.toolbar.navigationIcon?.mutate()?.setTint(R.color.neutrals1.res2color()) - activity.setSupportActionBar(binding.toolbar) - activity.supportActionBar?.setDisplayHomeAsUpEnabled(true) - activity.supportActionBar?.setDisplayShowHomeEnabled(true) - activity.title = R.string.add_collection.res2String() - } - - private fun onSearchFocusChange(hasFocus: Boolean) { - val isVisible = hasFocus || !binding.editText.text.isNullOrBlank() - val isVisibleChange = isVisible != binding.cancelButton.isVisible() - - if (isVisibleChange) { - TransitionManager.go(Scene(binding.root as ViewGroup), Slide(Gravity.END).apply { duration = 150 }) - binding.cancelButton.setVisible(isVisible) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/nft/nftlist/presenter/NFTFragmentPresenter.kt b/app/src/main/java/com/flowfoundation/wallet/page/nft/nftlist/presenter/NFTFragmentPresenter.kt index 75d3d7248..bd022948b 100644 --- a/app/src/main/java/com/flowfoundation/wallet/page/nft/nftlist/presenter/NFTFragmentPresenter.kt +++ b/app/src/main/java/com/flowfoundation/wallet/page/nft/nftlist/presenter/NFTFragmentPresenter.kt @@ -10,7 +10,8 @@ import com.flowfoundation.wallet.R import com.flowfoundation.wallet.base.presenter.BasePresenter import com.flowfoundation.wallet.databinding.FragmentNftBinding import com.flowfoundation.wallet.manager.wallet.WalletManager -import com.flowfoundation.wallet.page.nft.collectionlist.NftCollectionListActivity +import com.flowfoundation.wallet.reactnative.ReactNativeActivity +import com.flowfoundation.wallet.reactnative.bridge.RNBridge import com.flowfoundation.wallet.page.nft.nftlist.NFTFragment import com.flowfoundation.wallet.page.nft.nftlist.NftViewModel import com.flowfoundation.wallet.page.nft.nftlist.adapter.NftListPageAdapter @@ -36,7 +37,7 @@ class NFTFragmentPresenter( with(binding) { with(toolbar) { post { setPadding(paddingLeft, paddingTop + statusBarHeight, paddingRight, paddingBottom) } } viewPager.adapter = NftListPageAdapter(fragment) - addButton.setOnClickListener { NftCollectionListActivity.launch(fragment.requireContext()) } + addButton.setOnClickListener { ReactNativeActivity.launch(fragment.requireContext(), RNBridge.ScreenType.ADD_NFT_COLLECTION) } with(refreshLayout) { isEnabled = true diff --git a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/AddTokenActivity.kt b/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/AddTokenActivity.kt deleted file mode 100644 index 6e29d9d43..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/AddTokenActivity.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.flowfoundation.wallet.page.token.addtoken - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.view.MenuItem -import androidx.lifecycle.ViewModelProvider -import com.flowfoundation.wallet.base.activity.BaseActivity -import com.zackratos.ultimatebarx.ultimatebarx.UltimateBarX -import com.flowfoundation.wallet.databinding.ActivityAddTokenBinding -import com.flowfoundation.wallet.page.token.addtoken.model.AddTokenModel -import com.flowfoundation.wallet.page.token.addtoken.presenter.AddTokenPresenter -import com.flowfoundation.wallet.utils.isNightMode -import com.flowfoundation.wallet.widgets.FlowLoadingDialog - -class AddTokenActivity : BaseActivity() { - - private lateinit var presenter: AddTokenPresenter - private lateinit var viewModel: AddTokenViewModel - private lateinit var binding: ActivityAddTokenBinding - - private val loadingDialog by lazy { FlowLoadingDialog(this) } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding = ActivityAddTokenBinding.inflate(layoutInflater) - setContentView(binding.root) - - UltimateBarX.with(this).fitWindow(false).light(!isNightMode(this)).applyStatusBar() - UltimateBarX.with(this).fitWindow(true).light(!isNightMode(this)).applyNavigationBar() - - presenter = AddTokenPresenter(this, binding) - viewModel = ViewModelProvider(this)[AddTokenViewModel::class.java].apply { - tokenListLiveData.observe(this@AddTokenActivity) { - loadingDialog.dismiss() - presenter.bind(AddTokenModel(data = it)) - } - load() - loadingDialog.show() - } - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { - android.R.id.home -> finish() - else -> super.onOptionsItemSelected(item) - } - return true - } - - companion object { - fun launch(context: Context) { - context.startActivity(Intent(context, AddTokenActivity::class.java)) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/AddTokenConfirmDialog.kt b/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/AddTokenConfirmDialog.kt deleted file mode 100644 index 96e624a1c..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/AddTokenConfirmDialog.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.flowfoundation.wallet.page.token.addtoken - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.FragmentManager -import androidx.lifecycle.ViewModelProvider -import com.bumptech.glide.Glide -import com.google.android.material.bottomsheet.BottomSheetDialogFragment -import com.flowfoundation.wallet.databinding.DialogAddTokenConfirmBinding -import com.flowfoundation.wallet.network.model.TokenInfo -import com.flowfoundation.wallet.utils.uiScope - -class AddTokenConfirmDialog : BottomSheetDialogFragment() { - - private val info by lazy { arguments?.getParcelable(EXTRA_TOKEN)!! } - - private lateinit var binding: DialogAddTokenConfirmBinding - - private lateinit var viewModel: AddTokenViewModel - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - binding = DialogAddTokenConfirmBinding.inflate(inflater) - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - viewModel = ViewModelProvider(requireActivity())[AddTokenViewModel::class.java].apply { - cadenceExecuteLiveData.observe(this@AddTokenConfirmDialog) { - if (it) { - dismiss() - cadenceExecuteLiveData.value = false - } - } - } - - binding.closeButton.setOnClickListener { dismiss() } - with(binding) { - tokenNameView.text = info.tokenName() - Glide.with(iconView).load(info.icon()).into(iconView) - actionButton.setOnClickListener { - uiScope { - actionButton.setProgressVisible(true) - viewModel.addToken(info) - } - } - } - } - - companion object { - private const val EXTRA_TOKEN = "extra_token" - - fun show(fragmentManager: FragmentManager, info: TokenInfo) { - AddTokenConfirmDialog().apply { - arguments = Bundle().apply { - putParcelable(EXTRA_TOKEN, info) - } - }.show(fragmentManager, "") - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/AddTokenViewModel.kt b/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/AddTokenViewModel.kt deleted file mode 100644 index b80cc2797..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/AddTokenViewModel.kt +++ /dev/null @@ -1,147 +0,0 @@ -package com.flowfoundation.wallet.page.token.addtoken - -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import com.google.gson.Gson -import com.flowfoundation.wallet.R -import com.flowfoundation.wallet.manager.app.chainNetWorkString -import com.flowfoundation.wallet.manager.flowjvm.cadenceEnableToken -import com.flowfoundation.wallet.manager.token.FungibleTokenListManager -import com.flowfoundation.wallet.manager.token.FungibleTokenListUpdateListener -import com.flowfoundation.wallet.manager.token.model.FungibleToken -import com.flowfoundation.wallet.manager.transaction.OnTransactionStateChange -import com.flowfoundation.wallet.manager.transaction.TransactionState -import com.flowfoundation.wallet.manager.transaction.TransactionStateManager -import com.flowfoundation.wallet.network.ApiService -import com.flowfoundation.wallet.network.model.TokenInfo -import com.flowfoundation.wallet.network.retrofitApi -import com.flowfoundation.wallet.page.token.addtoken.model.TokenItem -import com.flowfoundation.wallet.page.window.bubble.tools.pushBubbleStack -import com.flowfoundation.wallet.utils.ioScope -import com.flowfoundation.wallet.utils.toast -import com.flowfoundation.wallet.utils.viewModelIOScope -import org.onflow.flow.models.TransactionStatus - -class AddTokenViewModel : ViewModel(), OnTransactionStateChange, FungibleTokenListUpdateListener { - - val tokenListLiveData = MutableLiveData>() - var cadenceExecuteLiveData = MutableLiveData() - private val service by lazy { retrofitApi().create(ApiService::class.java) } - - private val coinList = mutableListOf() - - private var transactionIds = mutableListOf() - - private var keyword = "" - private var isShowVerifiedToken = true - - init { - TransactionStateManager.addOnTransactionStateChange(this) - FungibleTokenListManager.addTokenListUpdateListener(this) - } - - fun load() { - viewModelIOScope(this) { - coinList.clear() - val tokenResponse = service.getAddTokenList(FullFungibleTokenListType.FLOW.name, chainNetWorkString()) - if (tokenResponse.tokens.isEmpty()) { - return@viewModelIOScope - } - - coinList.addAll( - tokenResponse.tokens.map { TokenItem(coin = it, isAdded = FungibleTokenListManager.isTokenAdded(it.contractId()), isAdding = false) }) - postTokenList(coinList.toList()) - onTransactionStateChange() - - } - } - - fun search(keyword: String) { - this.keyword = keyword - if (keyword.isBlank()) { - postTokenList(coinList.toList()) - } else { - postTokenList(coinList.filter { - it.coin.tokenName().contains(keyword, true) || it.coin.tokenSymbol().contains(keyword, true) - }) - } - } - - fun switchVerifiedToken(isChecked: Boolean) { - this.isShowVerifiedToken = isChecked - postTokenList(coinList.toList()) - } - - private fun postTokenList(tokenList: List) { - if (isShowVerifiedToken) { - tokenListLiveData.postValue(tokenList.filter { it.coin.isVerified }) - } else { - tokenListLiveData.postValue(tokenList.toList()) - } - } - - fun clearSearch() { - this.keyword = "" - search("") - } - - fun addToken(coin: TokenInfo) { - ioScope { - val transactionId = cadenceEnableToken(coin) - if (transactionId.isNullOrBlank()) { - toast(msgRes = R.string.add_token_failed) - } else { - val transactionState = TransactionState( - transactionId = transactionId, - time = System.currentTimeMillis(), - state = TransactionStatus.PENDING.ordinal, - type = TransactionState.TYPE_ADD_TOKEN, - data = Gson().toJson(coin) - ) - TransactionStateManager.newTransaction(transactionState) - pushBubbleStack(transactionState) - transactionIds.add(transactionId) - } - cadenceExecuteLiveData.postValue(true) - } - } - - override fun onTransactionStateChange() { - viewModelIOScope(this) { - val transactionList = TransactionStateManager.getTransactionStateList() - transactionList.forEach { state -> - if (state.type == TransactionState.TYPE_ADD_TOKEN) { - val coin = state.tokenData() - - if (state.isSuccess() && !FungibleTokenListManager.isTokenAdded(coin.contractId())) { - FungibleTokenListManager.updateTokenList(contractId = coin.contractId()) - } - val index = coinList.indexOfFirst { it.coin.isSameCoin(coin.contractId()) } - if (index >= 0) { - val isAdded = FungibleTokenListManager.isTokenAdded(coin.contractId()) - coinList[index] = TokenItem( - coin = coinList[index].coin, - isAdding = !state.isFailed() && !isAdded, - isAdded = isAdded, - ) - } - } - } - search(keyword) - } - } - - override fun onTokenListUpdated(list: List) { - onTransactionStateChange() - } - - override fun onTokenDisplayUpdated(token: FungibleToken, isAdd: Boolean) { - - } - -} - -enum class FullFungibleTokenListType(name: String) { - FLOW("flow"), - EVM("evm") -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/Utils.kt b/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/Utils.kt deleted file mode 100644 index 7506c665f..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/Utils.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.flowfoundation.wallet.page.token.addtoken - -import android.annotation.SuppressLint -import androidx.recyclerview.widget.DiffUtil -import com.flowfoundation.wallet.page.address.model.AddressBookPersonModel - - -val tokenListDiffCallback = object : DiffUtil.ItemCallback() { - override fun areItemsTheSame(oldItem: Any, newItem: Any): Boolean { - if (oldItem is AddressBookPersonModel && newItem is AddressBookPersonModel) { - return oldItem.data == newItem.data - } - return oldItem == newItem - } - - @SuppressLint("DiffUtilEquals") - override fun areContentsTheSame(oldItem: Any, newItem: Any): Boolean { - if (oldItem is AddressBookPersonModel && newItem is AddressBookPersonModel) { - return oldItem.data == newItem.data && oldItem.isFriend == newItem.isFriend - } - return oldItem == newItem - } -} diff --git a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/adapter/TokenListAdapter.kt b/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/adapter/TokenListAdapter.kt deleted file mode 100644 index 59efdf2ac..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/adapter/TokenListAdapter.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.flowfoundation.wallet.page.token.addtoken.adapter - -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import com.flowfoundation.wallet.R -import com.flowfoundation.wallet.base.recyclerview.BaseAdapter -import com.flowfoundation.wallet.base.recyclerview.BaseViewHolder -import com.flowfoundation.wallet.page.token.addtoken.model.TokenItem -import com.flowfoundation.wallet.page.token.addtoken.presenter.TokenItemPresenter -import com.flowfoundation.wallet.page.token.addtoken.tokenListDiffCallback - -class TokenListAdapter : BaseAdapter(tokenListDiffCallback) { - - override fun getItemViewType(position: Int): Int { - return TYPE_TOKEN - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - return when (viewType) { - TYPE_TOKEN -> TokenItemPresenter(parent.inflate(R.layout.item_add_token_list)) - else -> BaseViewHolder(View(parent.context)) - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is TokenItemPresenter -> holder.bind(getItem(position) as TokenItem) - } - } - - companion object { - private const val TYPE_TOKEN = 1 - } -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/model/AddTokenModel.kt b/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/model/AddTokenModel.kt deleted file mode 100644 index c269218ff..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/model/AddTokenModel.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.flowfoundation.wallet.page.token.addtoken.model - -class AddTokenModel( - val data: List? = null, -) \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/model/TokenItem.kt b/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/model/TokenItem.kt deleted file mode 100644 index 4876f1a61..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/model/TokenItem.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.flowfoundation.wallet.page.token.addtoken.model - -import com.flowfoundation.wallet.network.model.TokenInfo -import com.google.gson.annotations.SerializedName - -data class TokenItem( - @SerializedName("coin") - val coin: TokenInfo, - @SerializedName("isAdded") - var isAdded: Boolean, - @SerializedName("isAdding") - var isAdding: Boolean? = null, -) { - fun isNormalState() = !(isAdded || isAdding == true) -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/presenter/AddTokenPresenter.kt b/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/presenter/AddTokenPresenter.kt deleted file mode 100644 index 3a43fc3ef..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/presenter/AddTokenPresenter.kt +++ /dev/null @@ -1,106 +0,0 @@ -package com.flowfoundation.wallet.page.token.addtoken.presenter - -import android.graphics.Color -import android.transition.Scene -import android.transition.Slide -import android.transition.TransitionManager -import android.view.Gravity -import android.view.View -import android.view.ViewGroup -import android.view.inputmethod.EditorInfo -import androidx.core.widget.doOnTextChanged -import androidx.lifecycle.ViewModelProvider -import androidx.recyclerview.widget.LinearLayoutManager -import com.zackratos.ultimatebarx.ultimatebarx.addStatusBarTopPadding -import com.flowfoundation.wallet.R -import com.flowfoundation.wallet.base.presenter.BasePresenter -import com.flowfoundation.wallet.databinding.ActivityAddTokenBinding -import com.flowfoundation.wallet.page.token.addtoken.AddTokenActivity -import com.flowfoundation.wallet.page.token.addtoken.AddTokenViewModel -import com.flowfoundation.wallet.page.token.addtoken.adapter.TokenListAdapter -import com.flowfoundation.wallet.page.token.addtoken.model.AddTokenModel -import com.flowfoundation.wallet.utils.extensions.* -import com.flowfoundation.wallet.widgets.itemdecoration.ColorDividerItemDecoration - -class AddTokenPresenter( - private val activity: AddTokenActivity, - private val binding: ActivityAddTokenBinding, -) : BasePresenter { - - private val viewModel by lazy { ViewModelProvider(activity)[AddTokenViewModel::class.java] } - private val adapter by lazy { TokenListAdapter() } - - init { - binding.root.addStatusBarTopPadding() - setupToolbar() - setupEditText() - setupFilters() - setupRecyclerView() - } - - private fun setupFilters() { - with(binding) { - switchVerifiedToken.isChecked = true - switchVerifiedToken.setOnCheckedChangeListener { _, isChecked -> - viewModel.switchVerifiedToken(isChecked) - } - } - } - - override fun bind(model: AddTokenModel) { - model.data?.let { adapter.setNewDiffData(it) } - } - - private fun setupRecyclerView() { - with(binding.recyclerView) { - adapter = this@AddTokenPresenter.adapter - layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) - addItemDecoration( - ColorDividerItemDecoration(Color.TRANSPARENT, 12.dp2px().toInt()) - ) - } - } - - private fun setupEditText() { - with(binding.editText) { - setOnEditorActionListener { _, actionId, _ -> - if (actionId == EditorInfo.IME_ACTION_SEARCH) { - hideKeyboard() - viewModel.search(text.toString().trim()) - clearFocus() - } - return@setOnEditorActionListener false - } - doOnTextChanged { text, _, _, _ -> - viewModel.search(text.toString().trim()) - } - onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus -> onSearchFocusChange(hasFocus) } - } - - binding.cancelButton.setOnClickListener { - onSearchFocusChange(false) - binding.editText.hideKeyboard() - binding.editText.setText("") - binding.editText.clearFocus() - viewModel.clearSearch() - } - } - - private fun setupToolbar() { - binding.toolbar.navigationIcon?.mutate()?.setTint(R.color.neutrals1.res2color()) - activity.setSupportActionBar(binding.toolbar) - activity.supportActionBar?.setDisplayHomeAsUpEnabled(true) - activity.supportActionBar?.setDisplayShowHomeEnabled(true) - activity.title = R.string.add_token.res2String() - } - - private fun onSearchFocusChange(hasFocus: Boolean) { - val isVisible = hasFocus || !binding.editText.text.isNullOrBlank() - val isVisibleChange = isVisible != binding.cancelButton.isVisible() - - if (isVisibleChange) { - TransitionManager.go(Scene(binding.root as ViewGroup), Slide(Gravity.END).apply { duration = 150 }) - binding.cancelButton.setVisible(isVisible) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/presenter/TokenItemPresenter.kt b/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/presenter/TokenItemPresenter.kt deleted file mode 100644 index 3387f038d..000000000 --- a/app/src/main/java/com/flowfoundation/wallet/page/token/addtoken/presenter/TokenItemPresenter.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.flowfoundation.wallet.page.token.addtoken.presenter - -import android.view.View -import androidx.fragment.app.FragmentActivity -import com.bumptech.glide.Glide -import com.flowfoundation.wallet.R -import com.flowfoundation.wallet.base.presenter.BasePresenter -import com.flowfoundation.wallet.base.recyclerview.BaseViewHolder -import com.flowfoundation.wallet.databinding.ItemAddTokenListBinding -import com.flowfoundation.wallet.page.token.addtoken.AddTokenConfirmDialog -import com.flowfoundation.wallet.page.token.addtoken.model.TokenItem -import com.flowfoundation.wallet.utils.extensions.setVisible -import com.flowfoundation.wallet.utils.findActivity - -class TokenItemPresenter( - private val view: View, -) : BaseViewHolder(view), BasePresenter { - - private val binding by lazy { ItemAddTokenListBinding.bind(view) } - - override fun bind(model: TokenItem) { - with(binding) { - nameView.text = model.coin.tokenName() - symbolView.text = model.coin.tokenSymbol().uppercase() - Glide.with(iconView).load(model.coin.icon()).into(iconView) - ivVerified.setVisible(model.coin.isVerified) - stateButton.setOnClickListener { - if (model.isNormalState()) { - AddTokenConfirmDialog.show((findActivity(view) as FragmentActivity).supportFragmentManager, model.coin) - } - } - progressBar.setVisible(model.isAdding == true) - stateButton.setVisible(model.isAdding != true) - stateButton.setImageResource(if (model.isNormalState()) R.drawable.ic_add_circle else R.drawable.ic_check_round) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/flowfoundation/wallet/page/wallet/presenter/WalletHeaderPresenter.kt b/app/src/main/java/com/flowfoundation/wallet/page/wallet/presenter/WalletHeaderPresenter.kt index 1124d9833..24e083ce1 100644 --- a/app/src/main/java/com/flowfoundation/wallet/page/wallet/presenter/WalletHeaderPresenter.kt +++ b/app/src/main/java/com/flowfoundation/wallet/page/wallet/presenter/WalletHeaderPresenter.kt @@ -28,8 +28,6 @@ import com.flowfoundation.wallet.page.notification.model.Priority import com.flowfoundation.wallet.page.notification.model.Type import com.flowfoundation.wallet.page.notification.model.WalletNotification import com.flowfoundation.wallet.page.profile.subpage.walletconnect.session.model.PendingRequestModel -import com.flowfoundation.wallet.page.token.addtoken.AddTokenActivity -import com.flowfoundation.wallet.page.token.custom.AddCustomTokenActivity import com.flowfoundation.wallet.page.token.manage.ManageTokenActivity import com.flowfoundation.wallet.page.wallet.WalletFragmentViewModel import com.flowfoundation.wallet.page.wallet.dialog.SwapDialog @@ -94,9 +92,9 @@ class WalletHeaderPresenter( } else { flAddToken.setOnClickListener { if (WalletManager.isEVMAccountSelected()) { - AddCustomTokenActivity.launch(view.context) + com.flowfoundation.wallet.page.token.custom.AddCustomTokenActivity.launch(view.context) } else { - AddTokenActivity.launch(view.context) + ReactNativeActivity.launch(view.context, RNBridge.ScreenType.ADD_TOKENS) } } cvSwap.setOnClickListener { diff --git a/app/src/main/java/com/flowfoundation/wallet/reactnative/ReactNativeActivity.kt b/app/src/main/java/com/flowfoundation/wallet/reactnative/ReactNativeActivity.kt index dba837060..efb2efcd2 100644 --- a/app/src/main/java/com/flowfoundation/wallet/reactnative/ReactNativeActivity.kt +++ b/app/src/main/java/com/flowfoundation/wallet/reactnative/ReactNativeActivity.kt @@ -99,6 +99,8 @@ class ReactNativeActivity : ReactActivity() { RNBridge.ScreenType.ONBOARDING -> "onboarding" RNBridge.ScreenType.RECEIVE -> "receive" RNBridge.ScreenType.ACTIVITY -> "activity" + RNBridge.ScreenType.ADD_TOKENS -> "add-tokens" + RNBridge.ScreenType.ADD_NFT_COLLECTION -> "add-nft-collection" } } @@ -126,6 +128,8 @@ class ReactNativeActivity : ReactActivity() { RNBridge.ScreenType.ONBOARDING -> RNBridge.InitialRoute.GET_STARTED.routeName RNBridge.ScreenType.RECEIVE -> "Receive" RNBridge.ScreenType.ACTIVITY -> "Activity" + RNBridge.ScreenType.ADD_TOKENS -> RNBridge.InitialRoute.ADD_TOKENS.routeName + RNBridge.ScreenType.ADD_NFT_COLLECTION -> RNBridge.InitialRoute.ADD_NFT_COLLECTION.routeName } } diff --git a/app/src/main/java/com/flowfoundation/wallet/reactnative/bridge/BridgeModels.kt b/app/src/main/java/com/flowfoundation/wallet/reactnative/bridge/BridgeModels.kt index dbdca76ff..268566420 100644 --- a/app/src/main/java/com/flowfoundation/wallet/reactnative/bridge/BridgeModels.kt +++ b/app/src/main/java/com/flowfoundation/wallet/reactnative/bridge/BridgeModels.kt @@ -23,7 +23,9 @@ class RNBridge { @SerializedName("token-detail") TOKEN_DETAIL, @SerializedName("onboarding") ONBOARDING, @SerializedName("receive") RECEIVE, - @SerializedName("activity") ACTIVITY + @SerializedName("activity") ACTIVITY, + @SerializedName("add-tokens") ADD_TOKENS, + @SerializedName("add-nft-collection") ADD_NFT_COLLECTION } enum class AccountTypeType { @@ -423,7 +425,9 @@ class RNBridge { @SerializedName("SelectTokens") SELECT_TOKENS("SelectTokens"), @SerializedName("SendTo") SEND_TO("SendTo"), @SerializedName("SendTokens") SEND_TOKENS("SendTokens"), - @SerializedName("Home") HOME("Home") + @SerializedName("Home") HOME("Home"), + @SerializedName("AddTokens") ADD_TOKENS("AddTokens"), + @SerializedName("AddNFTCollection") ADD_NFT_COLLECTION("AddNFTCollection") } enum class NativeScreenName { diff --git a/app/src/main/java/com/flowfoundation/wallet/reactnative/bridge/NativeFRWBridge.kt b/app/src/main/java/com/flowfoundation/wallet/reactnative/bridge/NativeFRWBridge.kt index 26b704b3e..5cbd19961 100644 --- a/app/src/main/java/com/flowfoundation/wallet/reactnative/bridge/NativeFRWBridge.kt +++ b/app/src/main/java/com/flowfoundation/wallet/reactnative/bridge/NativeFRWBridge.kt @@ -81,6 +81,8 @@ class NativeFRWBridge(reactContext: ReactApplicationContext) : NativeFRWBridgeSp override fun closeRN(id: String?) = uiHandler.closeRN(id) + override fun closeRNWithNFT(id: String?) = uiHandler.closeRNWithNFT(id) + override fun getSignKeyIndex(): Double = accountHandler.getSignKeyIndex() override fun isFreeGasEnabled(promise: Promise) = utilsHandler.isFreeGasEnabled(promise) diff --git a/app/src/main/java/com/flowfoundation/wallet/reactnative/bridge/handlers/UIBridgeHandler.kt b/app/src/main/java/com/flowfoundation/wallet/reactnative/bridge/handlers/UIBridgeHandler.kt index 1119ef116..48da55dee 100644 --- a/app/src/main/java/com/flowfoundation/wallet/reactnative/bridge/handlers/UIBridgeHandler.kt +++ b/app/src/main/java/com/flowfoundation/wallet/reactnative/bridge/handlers/UIBridgeHandler.kt @@ -4,6 +4,13 @@ import android.content.Intent import android.widget.Toast import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext +import com.flowfoundation.wallet.manager.app.chainNetWorkString +import com.flowfoundation.wallet.manager.flowjvm.cadenceEnableToken +import com.flowfoundation.wallet.manager.flowjvm.cadenceNftEnabled +import com.flowfoundation.wallet.manager.transaction.TransactionState +import com.flowfoundation.wallet.manager.transaction.TransactionStateManager +import com.flowfoundation.wallet.network.ApiService +import com.flowfoundation.wallet.network.retrofitApi import com.flowfoundation.wallet.page.backup.BackupRecoveryPhraseActivity import com.flowfoundation.wallet.page.backup.WalletBackupActivity import com.flowfoundation.wallet.page.backup.device.CreateDeviceBackupActivity @@ -13,13 +20,17 @@ import com.flowfoundation.wallet.page.restore.keystore.KeyStoreRestoreActivity import com.flowfoundation.wallet.page.restore.multirestore.MultiRestoreActivity import com.flowfoundation.wallet.page.walletrestore.WalletRestoreActivity as GoogleDriveRestoreActivity import com.flowfoundation.wallet.page.scan.ScanBarcodeActivity +import com.flowfoundation.wallet.page.window.bubble.tools.pushBubbleStack import com.flowfoundation.wallet.reactnative.bridge.QRCodeScanManager import com.flowfoundation.wallet.reactnative.bridge.NativeScreen +import com.flowfoundation.wallet.utils.ioScope import com.flowfoundation.wallet.utils.logd import com.flowfoundation.wallet.utils.loge import com.flowfoundation.wallet.utils.logw import com.flowfoundation.wallet.utils.toast import com.flowfoundation.wallet.utils.uiScope +import com.google.gson.Gson +import org.onflow.flow.models.TransactionStatus /** * Handler for UI-related bridge methods @@ -53,35 +64,157 @@ class UIBridgeHandler(private val reactContext: ReactApplicationContext) { val currentActivity = reactContext.currentActivity logd(TAG, "closeRN() - currentActivity: ${currentActivity?.javaClass?.simpleName}, isFinishing: ${currentActivity?.isFinishing}, isDestroyed: ${currentActivity?.isDestroyed}") - if (currentActivity != null && !currentActivity.isFinishing && !currentActivity.isDestroyed) { - // Use runOnUiThread to ensure activity operations run on main thread + if (currentActivity == null || currentActivity.isFinishing || currentActivity.isDestroyed) { + logw(TAG, "closeRN() - Activity is null, finishing, or destroyed - skipping closeRN") + return + } + + // If a flowIdentifier is provided, close the screen immediately then execute the tx in background + if (!id.isNullOrBlank()) { + logd(TAG, "closeRN() - flowIdentifier provided, closing screen and triggering add token tx: $id") + // Close the activity first so the user isn't waiting on the API call currentActivity.runOnUiThread { + if (!currentActivity.isFinishing && !currentActivity.isDestroyed) { + currentActivity.setResult(android.app.Activity.RESULT_OK) + currentActivity.finish() + logd(TAG, "closeRN() - activity finished, tx will execute in background") + } + } + // Fetch token info and submit the Cadence tx in the background + ioScope { try { - if (!currentActivity.isFinishing && !currentActivity.isDestroyed) { - logd(TAG, "closeRN() - Calling finish() to close React Native activity and return to previous activity") - // Use finish() to close the activity and return to the previous activity in the task stack - // This should return to the native home screen that launched React Native - currentActivity.setResult(android.app.Activity.RESULT_OK) - currentActivity.finish() - logd(TAG, "closeRN() - finish() called successfully") + val service = retrofitApi().create(ApiService::class.java) + val tokenList = service.getAddTokenList("flow", chainNetWorkString()) + val coin = tokenList.tokens.firstOrNull { it.contractId() == id } + if (coin == null) { + logw(TAG, "closeRN() - token not found for contractId: $id") } else { - logw(TAG, "closeRN() - Activity already finishing or destroyed, skipping") + logd(TAG, "closeRN() - found token: ${coin.tokenName()}, executing cadenceEnableToken") + val transactionId = cadenceEnableToken(coin) + if (transactionId.isNullOrBlank()) { + loge(TAG, "closeRN() - cadenceEnableToken returned null/blank transactionId") + } else { + logd(TAG, "closeRN() - tx submitted: $transactionId") + val transactionState = TransactionState( + transactionId = transactionId, + time = System.currentTimeMillis(), + state = TransactionStatus.PENDING.ordinal, + type = TransactionState.TYPE_ADD_TOKEN, + data = Gson().toJson(coin) + ) + TransactionStateManager.newTransaction(transactionState) + pushBubbleStack(transactionState) + } } } catch (e: Exception) { - loge(TAG, "closeRN() - Failed to finish activity on UI thread: ${e.message}") + loge(TAG, "closeRN() - Failed to enable token: ${e.message}") e.printStackTrace() } } - } else { - logw(TAG, "closeRN() - Activity is null, finishing, or destroyed - skipping closeRN") + return + } + + // No flowIdentifier → just close the activity + currentActivity.runOnUiThread { + try { + if (!currentActivity.isFinishing && !currentActivity.isDestroyed) { + logd(TAG, "closeRN() - Calling finish() to close React Native activity") + currentActivity.setResult(android.app.Activity.RESULT_OK) + currentActivity.finish() + logd(TAG, "closeRN() - finish() called successfully") + } else { + logw(TAG, "closeRN() - Activity already finishing or destroyed, skipping") + } + } catch (e: Exception) { + loge(TAG, "closeRN() - Failed to finish activity on UI thread: ${e.message}") + e.printStackTrace() + } } } catch (e: Exception) { - // If finishing activity fails, log error but don't crash loge(TAG, "closeRN() - Failed to close React Native activity: ${e.message}") e.printStackTrace() } } + fun closeRNWithNFT(id: String?) { + logd(TAG, "closeRNWithNFT() called - id: $id") + try { + val currentActivity = reactContext.currentActivity + + if (currentActivity == null || currentActivity.isFinishing || currentActivity.isDestroyed) { + logw(TAG, "closeRNWithNFT() - Activity is null, finishing, or destroyed - skipping") + return + } + + if (!id.isNullOrBlank()) { + logd(TAG, "closeRNWithNFT() - flowIdentifier provided, closing screen and triggering enable NFT collection tx: $id") + // Close the activity first so the user isn't waiting on the API call + currentActivity.runOnUiThread { + if (!currentActivity.isFinishing && !currentActivity.isDestroyed) { + currentActivity.setResult(android.app.Activity.RESULT_OK) + currentActivity.finish() + logd(TAG, "closeRNWithNFT() - activity finished, tx will execute in background") + } + } + // Fetch NFT collection info and submit the Cadence tx in the background + ioScope { + try { + val service = retrofitApi().create(ApiService::class.java) + val response = service.getNFTCollections() + // Normalize id by stripping 0x from address segment (e.g. A.0x1234.Name → A.1234.Name) + // so it matches contractId() which always strips the 0x prefix + val normalizedId = id.replace(Regex("^A\\.0x"), "A.") + val collection = response.data.firstOrNull { it.contractId() == normalizedId || it.flowIdentifier == id } + if (collection == null) { + logw(TAG, "closeRNWithNFT() - NFT collection not found for flowIdentifier: $id") + } else { + logd(TAG, "closeRNWithNFT() - found collection: ${collection.name}, executing cadenceNftEnabled") + val transactionId = cadenceNftEnabled(collection) + if (transactionId.isNullOrBlank()) { + loge(TAG, "closeRNWithNFT() - cadenceNftEnabled returned null/blank transactionId") + } else { + logd(TAG, "closeRNWithNFT() - tx submitted: $transactionId") + val transactionState = TransactionState( + transactionId = transactionId, + time = System.currentTimeMillis(), + state = TransactionStatus.PENDING.ordinal, + type = TransactionState.TYPE_ENABLE_NFT, + data = Gson().toJson(collection) + ) + TransactionStateManager.newTransaction(transactionState) + pushBubbleStack(transactionState) + } + } + } catch (e: Exception) { + loge(TAG, "closeRNWithNFT() - Failed to enable NFT collection: ${e.message}") + e.printStackTrace() + } + } + return + } + + // No flowIdentifier → just close the activity + currentActivity.runOnUiThread { + try { + if (!currentActivity.isFinishing && !currentActivity.isDestroyed) { + logd(TAG, "closeRNWithNFT() - Calling finish() to close React Native activity") + currentActivity.setResult(android.app.Activity.RESULT_OK) + currentActivity.finish() + logd(TAG, "closeRNWithNFT() - finish() called successfully") + } else { + logw(TAG, "closeRNWithNFT() - Activity already finishing or destroyed, skipping") + } + } catch (e: Exception) { + loge(TAG, "closeRNWithNFT() - Failed to finish activity on UI thread: ${e.message}") + e.printStackTrace() + } + } + } catch (e: Exception) { + loge(TAG, "closeRNWithNFT() - Failed to close React Native activity: ${e.message}") + e.printStackTrace() + } + } + fun showToast(title: String, message: String?, type: String?, duration: Double?) { try { // Concatenate title and message diff --git a/app/src/main/res/layout/activity_add_token.xml b/app/src/main/res/layout/activity_add_token.xml deleted file mode 100644 index f73072aeb..000000000 --- a/app/src/main/res/layout/activity_add_token.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_nft_collection_list.xml b/app/src/main/res/layout/activity_nft_collection_list.xml deleted file mode 100644 index 6910cad6d..000000000 --- a/app/src/main/res/layout/activity_nft_collection_list.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/dialog_add_token_confirm.xml b/app/src/main/res/layout/dialog_add_token_confirm.xml deleted file mode 100644 index 0ffecdadf..000000000 --- a/app/src/main/res/layout/dialog_add_token_confirm.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_add_token_processing.xml b/app/src/main/res/layout/dialog_add_token_processing.xml deleted file mode 100644 index 71798720b..000000000 --- a/app/src/main/res/layout/dialog_add_token_processing.xml +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_add_token_list.xml b/app/src/main/res/layout/item_add_token_list.xml deleted file mode 100644 index d610a1c84..000000000 --- a/app/src/main/res/layout/item_add_token_list.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file