Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ class DeepLinkingActivity : BaseActivity() {
}

logd(TAG, "uri:$uri")

MainActivity.launch(this)
dispatchDeepLinking(uri)
dispatchDeepLinking(this, uri)
finish()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.flowfoundation.wallet.page.component.deeplinking

import android.content.Context
import android.content.SharedPreferences
import android.net.Uri


object PendingActionHelper {
private const val PREFS_NAME = "pending_action_prefs"
private const val KEY_PENDING_DEEPLINK = "pending_deeplink"
private const val KEY_HAS_PENDING_DEEPLINK = "has_pending_deeplink"

private fun getPrefs(context: Context): SharedPreferences {
return context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
}

fun savePendingDeepLink(context: Context, deepLink: Uri) {
getPrefs(context).edit().apply {
putString(KEY_PENDING_DEEPLINK, deepLink.toString())
putBoolean(KEY_HAS_PENDING_DEEPLINK, true)
commit()
}
}

fun hasPendingDeepLink(context: Context): Boolean {
return getPrefs(context).getBoolean(KEY_HAS_PENDING_DEEPLINK, false)
}

fun getPendingDeepLink(context: Context): Uri? {
val deepLinkStr = getPrefs(context).getString(KEY_PENDING_DEEPLINK, null) ?: return null
return Uri.parse(deepLinkStr)
}

fun clearPendingDeepLink(context: Context) {
getPrefs(context).edit().apply {
remove(KEY_PENDING_DEEPLINK)
putBoolean(KEY_HAS_PENDING_DEEPLINK, false)
commit()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,81 @@
package com.flowfoundation.wallet.page.component.deeplinking

import android.content.Context
import android.net.Uri
import com.flowfoundation.wallet.base.activity.BaseActivity
import com.flowfoundation.wallet.manager.app.chainNetWorkString
import com.flowfoundation.wallet.manager.app.networkId
import com.flowfoundation.wallet.manager.coin.FlowCoinListManager
import com.flowfoundation.wallet.manager.walletconnect.WalletConnect
import com.flowfoundation.wallet.network.model.AddressBookContact
import com.flowfoundation.wallet.page.browser.openBrowser
import com.flowfoundation.wallet.page.send.transaction.subpage.amount.SendAmountActivity
import com.flowfoundation.wallet.page.wallet.dialog.SwapDialog
import com.flowfoundation.wallet.utils.ioScope
import com.flowfoundation.wallet.utils.logd
import com.flowfoundation.wallet.utils.uiScope
import com.flowfoundation.wallet.wallet.toAddress
import com.flowfoundation.wallet.widgets.DialogType
import com.flowfoundation.wallet.widgets.SwitchNetworkDialog
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.web3j.utils.Convert
import org.web3j.utils.Numeric
import java.math.BigDecimal
import java.net.URLDecoder
import java.nio.charset.StandardCharsets

private const val TAG = "DeepLinkingDispatch"

fun dispatchDeepLinking(uri: Uri) {
ioScope { dispatchWalletConnect(uri) }
enum class DeepLinkPath(val path: String) {
DAPP("/dapp"),
SEND("/send"),
BUY("/buy");

companion object {
fun fromPath(path: String?): DeepLinkPath? {
return entries.firstOrNull { it.path == path }
}
}
Comment thread
jaymengxy marked this conversation as resolved.
}


fun dispatchDeepLinking(context: Context, uri: Uri) {
ioScope {
val wcUri = getWalletConnectUri(uri)
if (wcUri?.startsWith("wc:") == true) {
dispatchWalletConnect(uri)
return@ioScope
}
PendingActionHelper.savePendingDeepLink(context, uri)
}
}

fun executePendingDeepLink(uri: Uri) {
if (uri.host == "link.wallet.flow.com") {
when (DeepLinkPath.fromPath(uri.path)) {
DeepLinkPath.DAPP -> {
val dappUrl = uri.getQueryParameter("url")
if (dappUrl != null) {
dispatchDapp(dappUrl)
}
}
DeepLinkPath.SEND -> {
val recipient = uri.getQueryParameter("recipient")
val network = uri.getQueryParameter("network")
val value = uri.getQueryParameter("value")
if (recipient != null) {
dispatchSend(uri, recipient, network, parseValue(value))
}
Comment thread
jaymengxy marked this conversation as resolved.
}
DeepLinkPath.BUY -> {
dispatchBuy()
}
else -> {
logd(TAG, "executeDeepLinking: unknown path=${uri.path}")
}
}
}
}

// https://lilico.app/?uri=wc%3A83ba9cb3adf9da4b573ae0c499d49be91995aa3e38b5d9a41649adfaf986040c%402%3Frelay-protocol%3Diridium%26symKey%3D618e22482db56c3dda38b52f7bfca9515cc307f413694c1d6d91931bbe00ae90
Expand Down Expand Up @@ -55,3 +118,59 @@ fun getWalletConnectUri(uri: Uri): String? {
}
}.getOrNull()
}

private fun parseValue(value: String?): BigDecimal? {
if (value == null) return null

return try {
if (value.startsWith("0x", ignoreCase = true)) {
val amountValue = Numeric.decodeQuantity(value)
Convert.fromWei(amountValue.toString(), Convert.Unit.ETHER)
} else {
BigDecimal(value)
}
} catch (e: Exception) {
logd(TAG, "Failed to parse value: $value, ${e.message}")
null
}
}
Comment thread
jaymengxy marked this conversation as resolved.

private fun dispatchDapp(dappUrl: String) {
BaseActivity.getCurrentActivity()?.let {
uiScope {
openBrowser(it, dappUrl)
return@uiScope
}
}
}

private fun dispatchSend(uri: Uri, recipient: String, network: String?, value: BigDecimal?) {
logd(TAG, "dispatchSend: recipient=$recipient, network=$network, value=$value")
BaseActivity.getCurrentActivity()?.let {
if (network != null && network != chainNetWorkString()) {
PendingActionHelper.savePendingDeepLink(it, uri)
uiScope {
SwitchNetworkDialog(
context = it,
dialogType = DialogType.DEEPLINK,
targetNetwork = networkId(network)
).show()
}
} else {
SendAmountActivity.launch(
it,
AddressBookContact(address = recipient.toAddress()),
FlowCoinListManager.getFlowCoinContractId(),
value?.toString()
)
}
}
}

private fun dispatchBuy() {
BaseActivity.getCurrentActivity()?.let {
uiScope {
SwapDialog.show(it.supportFragmentManager)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import com.flowfoundation.wallet.base.activity.BaseActivity
import com.zackratos.ultimatebarx.ultimatebarx.UltimateBarX
import com.flowfoundation.wallet.databinding.ActivityMainBinding
import com.flowfoundation.wallet.firebase.firebaseInformationCheck
import com.flowfoundation.wallet.page.component.deeplinking.PendingActionHelper
import com.flowfoundation.wallet.page.component.deeplinking.executePendingDeepLink
import com.flowfoundation.wallet.page.dialog.common.RootDetectedDialog
import com.flowfoundation.wallet.page.main.model.MainContentModel
import com.flowfoundation.wallet.page.main.model.MainDrawerLayoutModel
Expand All @@ -30,7 +32,6 @@ import com.flowfoundation.wallet.utils.isRegistered
import com.flowfoundation.wallet.utils.uiScope
import com.instabug.bug.BugReporting
import com.instabug.library.Instabug
import com.instabug.library.OnSdkDismissCallback

class MainActivity : BaseActivity() {

Expand Down Expand Up @@ -111,6 +112,17 @@ class MainActivity : BaseActivity() {
override fun onResume() {
RootDetectedDialog.show(supportFragmentManager)
super.onResume()
checkPendingAction()
}

private fun checkPendingAction() {
if (PendingActionHelper.hasPendingDeepLink(this)) {
val pendingDeeplink = PendingActionHelper.getPendingDeepLink(this)
PendingActionHelper.clearPendingDeepLink(this)
if (pendingDeeplink != null) {
executePendingDeepLink(pendingDeeplink)
}
}
}

override fun onDestroy() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class SendAmountActivity : BaseActivity(), OnTransactionStateChange {

private val contact by lazy { intent.getParcelableExtra<AddressBookContact>(EXTRA_CONTACT)!! }
private val coinContractId by lazy { intent.getStringExtra(EXTRA_COIN_CONTRACT_ID) }
private val initialAmount by lazy { intent.getStringExtra(EXTRA_AMOUNT) }

private lateinit var binding: ActivitySendAmountBinding
private lateinit var presenter: SendAmountPresenter
Expand All @@ -38,6 +39,7 @@ class SendAmountActivity : BaseActivity(), OnTransactionStateChange {
presenter = SendAmountPresenter(this, binding, contact)
viewModel = ViewModelProvider(this)[SendAmountViewModel::class.java].apply {
setContact(contact)
setInitialAmount(initialAmount)
FlowCoinListManager.getCoinById(coinContractId.orEmpty())?.let { changeCoin(it) }
balanceLiveData.observe(this@SendAmountActivity) { presenter.bind(SendAmountModel(balance = it)) }
onCoinSwap.observe(this@SendAmountActivity) { presenter.bind(SendAmountModel(onCoinSwap = true)) }
Expand All @@ -61,11 +63,13 @@ class SendAmountActivity : BaseActivity(), OnTransactionStateChange {
companion object {
private const val EXTRA_CONTACT = "extra_contact"
private const val EXTRA_COIN_CONTRACT_ID = "coin_contract_id"
private const val EXTRA_AMOUNT = "extra_amount"

fun launch(context: Context, contact: AddressBookContact, coinContractId: String?) {
fun launch(context: Context, contact: AddressBookContact, coinContractId: String?, amount: String? = null) {
context.startActivity(Intent(context, SendAmountActivity::class.java).apply {
putExtra(EXTRA_CONTACT, contact)
putExtra(EXTRA_COIN_CONTRACT_ID, coinContractId)
putExtra(EXTRA_AMOUNT, amount)
})
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class SendAmountViewModel : ViewModel(), OnBalanceUpdate, OnCoinRateUpdate {
private lateinit var contact: AddressBookContact

val balanceLiveData = MutableLiveData<SendBalanceModel>()
private var initialAmount: String? = null

val onCoinSwap = MutableLiveData<Boolean>()

Expand All @@ -39,6 +40,12 @@ class SendAmountViewModel : ViewModel(), OnBalanceUpdate, OnCoinRateUpdate {

fun contact() = contact

fun setInitialAmount(amount: String?) {
this.initialAmount = amount
}

fun getInitialAmount() = initialAmount

fun load() {
viewModelIOScope(this) {
val coin = FlowCoinListManager.getCoinById(currentCoin) ?: return@viewModelIOScope
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class SendAmountPresenter(
private val viewModel by lazy { ViewModelProvider(activity)[SendAmountViewModel::class.java] }

private var minFlowBalance = BigDecimal.ZERO
private var initialAmountSet = false

private fun balance() = viewModel.balanceLiveData.value

Expand Down Expand Up @@ -78,10 +79,27 @@ class SendAmountPresenter(
}

override fun bind(model: SendAmountModel) {
model.balance?.let { updateBalance(it) }
model.balance?.let {
updateBalance(it)
if (!initialAmountSet) {
setInitialAmount()
initialAmountSet = true
}
}
model.onCoinSwap?.let { updateCoinState() }
}

private fun setInitialAmount() {
viewModel.getInitialAmount()?.let { amount ->
if (amount.isNotBlank()) {
with(binding) {
transferAmountInput.setText(amount)
transferAmountInput.setSelection(transferAmountInput.text.length)
Comment thread
jaymengxy marked this conversation as resolved.
}
}
}
}

private fun getMinFlowBalance() {
ioScope {
minFlowBalance = try {
Expand Down
Loading