Skip to content

Commit

Permalink
Merge pull request #31 from MrStahlfelge/develop
Browse files Browse the repository at this point in the history
Version 1.2.2113
  • Loading branch information
MrStahlfelge authored Aug 24, 2021
2 parents 38648a4 + fb82c52 commit 2e96af0
Show file tree
Hide file tree
Showing 13 changed files with 358 additions and 57 deletions.
8 changes: 6 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ android {
applicationId "org.ergoplatform.android"
minSdkVersion 24
targetSdkVersion 30
versionCode 2112
versionName "1.2.2112"
versionCode 2113
versionName "1.2.2113"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down Expand Up @@ -119,6 +119,10 @@ dependencies {

implementation('com.journeyapps:zxing-android-embedded:4.2.0')

// newer okhttp version than pulled from dependencies to avoid StrictMode policy violation
implementation("com.squareup.okhttp3:okhttp:3.12.13")
implementation("com.squareup.okhttp3:okhttp-urlconnection:3.12.13")

testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<nav-graph android:value="@navigation/mobile_navigation" />
</activity>

<activity
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/org/ergoplatform/android/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.ergoplatform.android

import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
Expand Down Expand Up @@ -37,4 +38,9 @@ class MainActivity : AppCompatActivity() {
override fun onSupportNavigateUp(): Boolean {
return findNavController(R.id.nav_host_fragment).navigateUp() || super.onSupportNavigateUp()
}

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
findNavController(R.id.nav_host_fragment).handleDeepLink(intent)
}
}
73 changes: 40 additions & 33 deletions app/src/main/java/org/ergoplatform/android/QRUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,44 +47,51 @@ fun parseContentFromQrCode(qrCode: String): QrCodeContent? {
if (qrCode.startsWith(PAYMENT_URI_PREFIX, true)) {
// we have a payment uri
val uriWithoutPrefix = qrCode.substring(PAYMENT_URI_PREFIX.length)
var address: String? = null
var amount: Float = 0f
var description: String = ""
val tokenMap: HashMap<String, Double> = HashMap()
return parseContentFromQuery(uriWithoutPrefix)

uriWithoutPrefix.split('&').forEach {
if (it.startsWith(RECIPIENT_PARAM_PREFIX)) {
address =
URLDecoder.decode(it.substring(RECIPIENT_PARAM_PREFIX.length), URI_ENCODING)
} else if (it.startsWith(AMOUNT_PARAM_PREFIX)) {
amount = URLDecoder.decode(it.substring(AMOUNT_PARAM_PREFIX.length), URI_ENCODING)
.toFloatOrNull() ?: 0f
} else if (it.startsWith(DESCRIPTION_PARAM_PREFIX)) {
description =
URLDecoder.decode(it.substring(DESCRIPTION_PARAM_PREFIX.length), URI_ENCODING)
} else if (it.contains('=')) {
// this could be a token
val keyVal = it.split("=")
try {
val tokenId = keyVal.get(0)
val tokenAmount = keyVal.get(1).toDouble()
tokenMap.put(tokenId, tokenAmount)
} catch (t: Throwable) {
// in this case, we haven't found a token :)
}
}
}
} else if (isValidErgoAddress(qrCode)) {
return QrCodeContent(qrCode)
} else {
return null
}
}

fun parseContentFromQuery(query: String): QrCodeContent? {
var address: String? = null
var amount = 0f
var description = ""
val tokenMap: HashMap<String, Double> = HashMap()

if (address != null) {
return QrCodeContent(address!!, amount, description, tokenMap)
} else {
// no recipient, no sense
return null
query.split('&').forEach {
if (it.startsWith(RECIPIENT_PARAM_PREFIX)) {
address =
URLDecoder.decode(it.substring(RECIPIENT_PARAM_PREFIX.length), URI_ENCODING)
} else if (it.startsWith(AMOUNT_PARAM_PREFIX)) {
amount = URLDecoder.decode(it.substring(AMOUNT_PARAM_PREFIX.length), URI_ENCODING)
.toFloatOrNull() ?: 0f
if (amount.isNaN()) {
amount = 0f
}
} else if (it.startsWith(DESCRIPTION_PARAM_PREFIX)) {
description =
URLDecoder.decode(it.substring(DESCRIPTION_PARAM_PREFIX.length), URI_ENCODING)
} else if (it.contains('=')) {
// this could be a token
val keyVal = it.split('=')
try {
val tokenId = keyVal.get(0)
val tokenAmount = keyVal.get(1).toDouble()
tokenMap.put(tokenId, tokenAmount)
} catch (t: Throwable) {
// in this case, we haven't found a token :)
}
}
}

} else if (isValidErgoAddress(qrCode)) {
return QrCodeContent(qrCode)
if (address != null) {
return QrCodeContent(address!!, amount, description, tokenMap)
} else {
// no recipient, no sense
return null
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package org.ergoplatform.android.transactions

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.NavOptions
import androidx.navigation.fragment.NavHostFragment
import org.ergoplatform.android.AppDatabase
import org.ergoplatform.android.R
import org.ergoplatform.android.databinding.FragmentSendFundsWalletChooserBinding
import org.ergoplatform.android.databinding.FragmentSendFundsWalletChooserItemBinding
import org.ergoplatform.android.nanoErgsToErgs
import org.ergoplatform.android.parseContentFromQuery
import org.ergoplatform.android.ui.FullScreenFragmentDialog
import org.ergoplatform.android.ui.navigateSafe


/**
* Deep link to send funds: Choose wallet to spend from
*/
class ChooseSpendingWalletFragmentDialog : FullScreenFragmentDialog() {

private var _binding: FragmentSendFundsWalletChooserBinding? = null

// This property is only valid between onCreateDialog and
// onDestroyView.
private val binding get() = _binding!!

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentSendFundsWalletChooserBinding.inflate(inflater, container, false)
// Inflate the layout for this fragment
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val query = requireActivity().intent.data?.encodedQuery

if (query == null) {
dismiss()
return
}

val content = parseContentFromQuery(query)
binding.receiverAddress.text = content?.address
val amount = content?.amount ?: 0f
binding.grossAmount.amount = amount
binding.grossAmount.visibility = if (amount > 0f) View.VISIBLE else View.GONE

AppDatabase.getInstance(requireContext()).walletDao().getWalletsWithStates()
.observe(viewLifecycleOwner, {
binding.listWallets.removeAllViews()

val walletsWithoutReadonly = it.filter { it.walletConfig.secretStorage != null }

if (walletsWithoutReadonly.size == 1) {
// immediately switch to send funds screen
navigateToSendFundsScreen(walletsWithoutReadonly.first().walletConfig.id, true)
}
walletsWithoutReadonly.forEach { wallet ->
val itemBinding = FragmentSendFundsWalletChooserItemBinding.inflate(
layoutInflater, binding.listWallets, true
)

itemBinding.walletBalance.amount =
nanoErgsToErgs(wallet.state.map { it.balance ?: 0 }.sum())
itemBinding.walletName.text = wallet.walletConfig.displayName

itemBinding.root.setOnClickListener {
navigateToSendFundsScreen(wallet.walletConfig.id, false)
}
}
})
}

private fun navigateToSendFundsScreen(walletId: Int, popThis: Boolean) {
val navBuilder = NavOptions.Builder()
val navOptions =
navBuilder.setPopUpTo(R.id.chooseSpendingWalletFragmentDialog, popThis).build()

NavHostFragment.findNavController(requireParentFragment())
.navigateSafe(
ChooseSpendingWalletFragmentDialogDirections.actionChooseSpendingWalletFragmentDialogToSendFundsFragment(
requireActivity().intent.data?.encodedQuery!!, walletId
), navOptions
)
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@ import com.google.zxing.integration.android.IntentIntegrator
import org.ergoplatform.android.*
import org.ergoplatform.android.databinding.FragmentSendFundsBinding
import org.ergoplatform.android.databinding.FragmentSendFundsTokenItemBinding
import org.ergoplatform.android.ui.FullScreenFragmentDialog
import org.ergoplatform.android.ui.PasswordDialogCallback
import org.ergoplatform.android.ui.hideForcedSoftKeyboard
import org.ergoplatform.android.ui.inputTextToFloat
import org.ergoplatform.android.ui.*
import org.ergoplatform.android.wallet.WalletTokenDbEntity
import kotlin.math.pow

Expand Down Expand Up @@ -55,7 +52,7 @@ class SendFundsFragmentDialog : FullScreenFragmentDialog(), PasswordDialogCallba
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

viewModel.initWallet(requireContext(), args.walletId)
viewModel.initWallet(requireContext(), args.walletId, args.paymentRequest)

// Add observers
viewModel.walletName.observe(viewLifecycleOwner, {
Expand Down Expand Up @@ -360,7 +357,7 @@ class SendFundsFragmentDialog : FullScreenFragmentDialog(), PasswordDialogCallba
override fun afterTextChanged(s: Editable?) {
viewModel.setTokenAmount(
token.tokenId!!,
(inputTextToFloat(s?.toString()) * 10f.pow(token.decimals!!)).toLong()
(inputTextToDouble(s?.toString()) * 10.0.pow(token.decimals!!)).toLong()
)
binding.labelTokenAmountError.visibility = View.GONE
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,20 @@ class SendFundsViewModel : ViewModel() {
private val _tokensChosenLiveData = MutableLiveData<List<String>>()
val tokensChosenLiveData: LiveData<List<String>> = _tokensChosenLiveData

fun initWallet(ctx: Context, walletId: Int) {
fun initWallet(ctx: Context, walletId: Int, paymentRequest: String?) {
val firstInit = wallet == null

// on first init, we read an send payment request. Don't do it again on device rotation
// to not mess with user inputs
val content: QrCodeContent?
if (firstInit) {
content = paymentRequest?.let { parseContentFromQuery(paymentRequest) }
content?.let {
receiverAddress = content.address
amountToSend = content.amount
}
} else content = null

viewModelScope.launch {
val walletWithState =
AppDatabase.getInstance(ctx).walletDao().loadWalletWithStateById(walletId)
Expand All @@ -78,6 +91,7 @@ class SendFundsViewModel : ViewModel() {
?.let { _walletBalance.postValue(nanoErgsToErgs(it)) }
tokensAvail.clear()
walletWithState?.tokens?.let { tokensAvail.addAll(it) }
content?.let { addTokensFromQr(content.tokens) }
notifyTokensChosenChanged()
}
calcGrossAmount()
Expand Down
14 changes: 11 additions & 3 deletions app/src/main/java/org/ergoplatform/android/ui/UiUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fun hideForcedSoftKeyboard(context: Context, editText: EditText) {
ContextCompat.getSystemService(
context,
InputMethodManager::class.java
)?.hideSoftInputFromWindow(editText.getWindowToken(), 0);
)?.hideSoftInputFromWindow(editText.getWindowToken(), 0)
}

fun inputTextToFloat(amountStr: String?): Float {
Expand All @@ -34,6 +34,14 @@ fun inputTextToFloat(amountStr: String?): Float {
}
}

fun inputTextToDouble(amountStr: String?): Double {
try {
return if (amountStr.isNullOrEmpty()) 0.0 else amountStr.toDouble()
} catch (t: Throwable) {
return 0.0
}
}

/**
* prevents crashes when a button is tapped twice, see
* https://stackoverflow.com/questions/51060762/illegalargumentexception-navigation-destination-xxx-is-unknown-to-this-navcontr
Expand All @@ -52,6 +60,6 @@ fun NavController.navigateSafe(
}
}

fun NavController.navigateSafe(directions: NavDirections) {
navigateSafe(directions.actionId, directions.arguments)
fun NavController.navigateSafe(directions: NavDirections, navOptions: NavOptions? = null) {
navigateSafe(directions.actionId, directions.arguments, navOptions)
}
Loading

0 comments on commit 2e96af0

Please sign in to comment.