mirror of
https://codeberg.org/anoncontributorxmr/mysu.git
synced 2024-12-22 13:07:46 +00:00
Refactoring settings/onboarding screens
This commit is contained in:
parent
3b77ae3673
commit
bd67d6d4bd
9 changed files with 468 additions and 577 deletions
|
@ -1,10 +1,8 @@
|
||||||
package net.mynero.wallet.fragment.onboarding
|
package net.mynero.wallet.fragment.onboarding
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
import android.util.Patterns
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -18,13 +16,12 @@ import android.widget.Toast
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.appcompat.widget.SwitchCompat
|
import androidx.appcompat.widget.SwitchCompat
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.widget.addTextChangedListener
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import net.mynero.wallet.MoneroApplication
|
|
||||||
import net.mynero.wallet.R
|
import net.mynero.wallet.R
|
||||||
import net.mynero.wallet.data.Node
|
import net.mynero.wallet.data.Node
|
||||||
import net.mynero.wallet.fragment.dialog.AddNodeBottomSheetDialog
|
import net.mynero.wallet.fragment.dialog.AddNodeBottomSheetDialog
|
||||||
|
@ -32,9 +29,9 @@ import net.mynero.wallet.fragment.dialog.AddNodeBottomSheetDialog.AddNodeListene
|
||||||
import net.mynero.wallet.fragment.dialog.NodeSelectionBottomSheetDialog
|
import net.mynero.wallet.fragment.dialog.NodeSelectionBottomSheetDialog
|
||||||
import net.mynero.wallet.fragment.dialog.NodeSelectionBottomSheetDialog.NodeSelectionDialogListener
|
import net.mynero.wallet.fragment.dialog.NodeSelectionBottomSheetDialog.NodeSelectionDialogListener
|
||||||
import net.mynero.wallet.fragment.onboarding.OnboardingViewModel.SeedType
|
import net.mynero.wallet.fragment.onboarding.OnboardingViewModel.SeedType
|
||||||
|
import net.mynero.wallet.model.EnumTorState
|
||||||
import net.mynero.wallet.service.PrefService
|
import net.mynero.wallet.service.PrefService
|
||||||
import net.mynero.wallet.service.ProxyService
|
import net.mynero.wallet.service.ProxyService
|
||||||
import net.mynero.wallet.util.Constants
|
|
||||||
|
|
||||||
class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListener {
|
class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListener {
|
||||||
private var useOffset = true
|
private var useOffset = true
|
||||||
|
@ -56,6 +53,7 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
|
||||||
private var xmrchanOnboardingImage: ImageView? = null
|
private var xmrchanOnboardingImage: ImageView? = null
|
||||||
private var seedTypeButton: Button? = null
|
private var seedTypeButton: Button? = null
|
||||||
private var seedTypeDescTextView: TextView? = null
|
private var seedTypeDescTextView: TextView? = null
|
||||||
|
private var useBundledTor: CheckBox? = null
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
|
@ -83,11 +81,38 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
|
||||||
xmrchanOnboardingImage = view.findViewById(R.id.xmrchan_onboarding_imageview)
|
xmrchanOnboardingImage = view.findViewById(R.id.xmrchan_onboarding_imageview)
|
||||||
seedTypeButton = view.findViewById(R.id.seed_type_button)
|
seedTypeButton = view.findViewById(R.id.seed_type_button)
|
||||||
seedTypeDescTextView = view.findViewById(R.id.seed_type_desc_textview)
|
seedTypeDescTextView = view.findViewById(R.id.seed_type_desc_textview)
|
||||||
|
useBundledTor = view.findViewById(R.id.bundled_tor_checkbox)
|
||||||
|
|
||||||
|
seedOffsetCheckbox?.isChecked = useOffset
|
||||||
|
showXmrchanSwitch?.isChecked = true
|
||||||
|
val usingProxy = ProxyService.instance?.usingProxy == true
|
||||||
|
val usingBundledTor = ProxyService.instance?.useBundledTor == true
|
||||||
|
|
||||||
|
torSwitch?.isChecked = usingProxy
|
||||||
|
useBundledTor?.isChecked = usingBundledTor
|
||||||
|
useBundledTor?.isEnabled = usingProxy
|
||||||
|
walletProxyAddressEditText?.isEnabled = usingProxy && !usingBundledTor
|
||||||
|
walletProxyPortEditText?.isEnabled = usingProxy && !usingBundledTor
|
||||||
|
walletProxyPortEditText?.visibility = if (usingBundledTor) View.GONE else View.VISIBLE
|
||||||
|
walletProxyAddressEditText?.visibility = if (usingBundledTor) View.GONE else View.VISIBLE
|
||||||
|
|
||||||
|
val node = PrefService.instance?.node // should be using default here
|
||||||
|
selectNodeButton?.text = getString(R.string.node_button_text, node?.address)
|
||||||
|
|
||||||
bindListeners()
|
bindListeners()
|
||||||
bindObservers()
|
bindObservers()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindObservers() {
|
private fun bindObservers() {
|
||||||
|
mViewModel?.passphrase?.observe(viewLifecycleOwner) { text ->
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
walletPasswordConfirmEditText?.text = null
|
||||||
|
walletPasswordConfirmEditText?.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
walletPasswordConfirmEditText?.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mViewModel?.showMoreOptions?.observe(viewLifecycleOwner) { show: Boolean ->
|
mViewModel?.showMoreOptions?.observe(viewLifecycleOwner) { show: Boolean ->
|
||||||
if (show) {
|
if (show) {
|
||||||
moreOptionsChevronImageView?.setImageResource(R.drawable.ic_keyboard_arrow_up)
|
moreOptionsChevronImageView?.setImageResource(R.drawable.ic_keyboard_arrow_up)
|
||||||
|
@ -97,9 +122,11 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
|
||||||
advancedOptionsLayout?.visibility = View.GONE
|
advancedOptionsLayout?.visibility = View.GONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mViewModel?.enableButton?.observe(viewLifecycleOwner) { enable: Boolean ->
|
mViewModel?.enableButton?.observe(viewLifecycleOwner) { enable: Boolean ->
|
||||||
createWalletButton?.isEnabled = enable
|
createWalletButton?.isEnabled = enable
|
||||||
}
|
}
|
||||||
|
|
||||||
mViewModel?.seedType?.observe(viewLifecycleOwner) { seedType: SeedType ->
|
mViewModel?.seedType?.observe(viewLifecycleOwner) { seedType: SeedType ->
|
||||||
seedTypeButton?.text = seedType.toString()
|
seedTypeButton?.text = seedType.toString()
|
||||||
seedTypeDescTextView?.text = getText(seedType.descResId)
|
seedTypeDescTextView?.text = getText(seedType.descResId)
|
||||||
|
@ -116,59 +143,92 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mViewModel?.showMonerochan?.observe(viewLifecycleOwner) {
|
||||||
|
if (it) {
|
||||||
|
xmrchanOnboardingImage?.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
xmrchanOnboardingImage?.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mViewModel?.useBundledTor?.observe(viewLifecycleOwner) { isChecked ->
|
||||||
|
walletProxyPortEditText?.visibility = if (isChecked) View.GONE else View.VISIBLE
|
||||||
|
walletProxyAddressEditText?.visibility = if (isChecked) View.GONE else View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
mViewModel?.useProxy?.observe(viewLifecycleOwner) { useProxy ->
|
||||||
|
useBundledTor?.isEnabled = useProxy
|
||||||
|
walletProxyAddressEditText?.isEnabled = useProxy
|
||||||
|
walletProxyPortEditText?.isEnabled = useProxy
|
||||||
|
}
|
||||||
|
|
||||||
val samouraiTorManager = ProxyService.instance?.samouraiTorManager
|
val samouraiTorManager = ProxyService.instance?.samouraiTorManager
|
||||||
samouraiTorManager?.getTorStateLiveData()?.observeForever {
|
val indicatorCircle = view?.findViewById<CircularProgressIndicator>(R.id.onboarding_tor_loading_progressindicator)
|
||||||
println("STATE CHANGE:: ${it.state.name}")
|
val torIcon = view?.findViewById<ImageView>(R.id.onboarding_tor_icon)
|
||||||
|
|
||||||
|
samouraiTorManager?.getTorStateLiveData()?.observe(viewLifecycleOwner) { state ->
|
||||||
samouraiTorManager.getProxy()?.address()?.let { socketAddress ->
|
samouraiTorManager.getProxy()?.address()?.let { socketAddress ->
|
||||||
if(socketAddress.toString().isEmpty()) return@let
|
if(socketAddress.toString().isEmpty()) return@let
|
||||||
println("PROXY INIT")
|
|
||||||
val proxyString = socketAddress.toString().substring(1)
|
val proxyString = socketAddress.toString().substring(1)
|
||||||
val address = proxyString.split(":")[0]
|
val address = proxyString.split(":")[0]
|
||||||
val port = proxyString.split(":")[1]
|
val port = proxyString.split(":")[1]
|
||||||
if(mViewModel?.useProxy?.value == true && mViewModel?.useBundledTor?.value == true) {
|
if(mViewModel?.useProxy?.value == true && mViewModel?.useBundledTor?.value == true) {
|
||||||
mViewModel?.setProxyAddress(address)
|
mViewModel?.setProxyAddress(address)
|
||||||
mViewModel?.setProxyPort(port)
|
mViewModel?.setProxyPort(port)
|
||||||
|
torIcon?.visibility = View.VISIBLE
|
||||||
|
indicatorCircle?.visibility = View.INVISIBLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
indicatorCircle?.isIndeterminate = state.progressIndicator == 0
|
||||||
|
indicatorCircle?.progress = state.progressIndicator
|
||||||
|
|
||||||
|
when (state.state) {
|
||||||
|
EnumTorState.OFF -> {
|
||||||
|
torIcon?.visibility = View.INVISIBLE
|
||||||
|
indicatorCircle?.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
EnumTorState.STARTING -> {
|
||||||
|
torIcon?.visibility = View.INVISIBLE
|
||||||
|
indicatorCircle?.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
EnumTorState.STOPPING -> {
|
||||||
|
torIcon?.visibility = View.INVISIBLE
|
||||||
|
indicatorCircle?.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindListeners() {
|
private fun bindListeners() {
|
||||||
val useBundledTor = view?.findViewById<CheckBox>(R.id.bundled_tor_checkbox)
|
|
||||||
|
|
||||||
seedOffsetCheckbox?.isChecked = useOffset
|
|
||||||
// Disable onBack click
|
// Disable onBack click
|
||||||
val onBackPressedCallback: OnBackPressedCallback = object : OnBackPressedCallback(true) {
|
val onBackPressedCallback: OnBackPressedCallback = object : OnBackPressedCallback(true) {
|
||||||
override fun handleOnBackPressed() {}
|
override fun handleOnBackPressed() {}
|
||||||
}
|
}
|
||||||
val activity = activity
|
|
||||||
activity?.onBackPressedDispatcher?.addCallback(viewLifecycleOwner, onBackPressedCallback)
|
activity?.onBackPressedDispatcher?.addCallback(viewLifecycleOwner, onBackPressedCallback)
|
||||||
|
|
||||||
moreOptionsDropdownTextView?.setOnClickListener { mViewModel?.onMoreOptionsClicked() }
|
moreOptionsDropdownTextView?.setOnClickListener { mViewModel?.onMoreOptionsClicked() }
|
||||||
|
|
||||||
moreOptionsChevronImageView?.setOnClickListener { mViewModel?.onMoreOptionsClicked() }
|
moreOptionsChevronImageView?.setOnClickListener { mViewModel?.onMoreOptionsClicked() }
|
||||||
|
|
||||||
seedOffsetCheckbox?.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
seedOffsetCheckbox?.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
||||||
useOffset = b
|
useOffset = b
|
||||||
}
|
}
|
||||||
|
|
||||||
createWalletButton?.setOnClickListener {
|
createWalletButton?.setOnClickListener {
|
||||||
onBackPressedCallback.isEnabled = false
|
onBackPressedCallback.isEnabled = false
|
||||||
(getActivity()?.application as MoneroApplication).executor?.execute {
|
createOrImportWallet(
|
||||||
createOrImportWallet(
|
walletSeedEditText?.text.toString().trim { it <= ' ' },
|
||||||
walletSeedEditText?.text.toString().trim { it <= ' ' },
|
walletRestoreHeightEditText?.text.toString().trim { it <= ' ' }
|
||||||
walletRestoreHeightEditText?.text.toString().trim { it <= ' ' }
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
walletPasswordEditText?.addTextChangedListener(object : TextWatcher {
|
walletPasswordEditText?.addTextChangedListener(object : TextWatcher {
|
||||||
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||||
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||||
override fun afterTextChanged(editable: Editable) {
|
override fun afterTextChanged(editable: Editable) {
|
||||||
val text = editable.toString()
|
mViewModel?.setPassphrase(editable.toString())
|
||||||
mViewModel?.setPassphrase(text)
|
|
||||||
if (text.isEmpty()) {
|
|
||||||
walletPasswordConfirmEditText?.text = null
|
|
||||||
walletPasswordConfirmEditText?.visibility = View.GONE
|
|
||||||
} else {
|
|
||||||
walletPasswordConfirmEditText?.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -176,10 +236,10 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
|
||||||
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||||
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||||
override fun afterTextChanged(editable: Editable) {
|
override fun afterTextChanged(editable: Editable) {
|
||||||
val text = editable.toString()
|
mViewModel?.setConfirmedPassphrase(editable.toString())
|
||||||
mViewModel?.setConfirmedPassphrase(text)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
walletSeedEditText?.addTextChangedListener(object : TextWatcher {
|
walletSeedEditText?.addTextChangedListener(object : TextWatcher {
|
||||||
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||||
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||||
|
@ -192,19 +252,13 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
seedTypeButton?.setOnClickListener { toggleSeedType() }
|
seedTypeButton?.setOnClickListener { toggleSeedType() }
|
||||||
torSwitch?.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
|
||||||
if (b) {
|
torSwitch?.setOnCheckedChangeListener { _, b: Boolean ->
|
||||||
useBundledTor?.visibility = View.VISIBLE
|
|
||||||
walletProxyAddressEditText?.visibility = View.VISIBLE
|
|
||||||
walletProxyPortEditText?.visibility = View.VISIBLE
|
|
||||||
} else {
|
|
||||||
useBundledTor?.visibility = View.GONE
|
|
||||||
walletProxyAddressEditText?.visibility = View.GONE
|
|
||||||
walletProxyPortEditText?.visibility = View.GONE
|
|
||||||
}
|
|
||||||
mViewModel?.setUseProxy(b)
|
mViewModel?.setUseProxy(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
walletProxyPortEditText?.addTextChangedListener(object : TextWatcher {
|
walletProxyPortEditText?.addTextChangedListener(object : TextWatcher {
|
||||||
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||||
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||||
|
@ -213,6 +267,7 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
|
||||||
mViewModel?.setProxyPort(text)
|
mViewModel?.setProxyPort(text)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
walletProxyAddressEditText?.addTextChangedListener(object : TextWatcher {
|
walletProxyAddressEditText?.addTextChangedListener(object : TextWatcher {
|
||||||
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||||
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||||
|
@ -221,16 +276,11 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
|
||||||
mViewModel?.setProxyAddress(text)
|
mViewModel?.setProxyAddress(text)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
showXmrchanSwitch?.isChecked = true
|
|
||||||
showXmrchanSwitch?.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
showXmrchanSwitch?.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
||||||
if (b) {
|
mViewModel?.setMonerochan(b)
|
||||||
xmrchanOnboardingImage?.visibility = View.VISIBLE
|
|
||||||
} else {
|
|
||||||
xmrchanOnboardingImage?.visibility = View.GONE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
val node = PrefService.instance?.node // should be using default here
|
|
||||||
selectNodeButton?.text = getString(R.string.node_button_text, node?.address)
|
|
||||||
selectNodeButton?.setOnClickListener {
|
selectNodeButton?.setOnClickListener {
|
||||||
activity?.supportFragmentManager?.let { fragmentManager ->
|
activity?.supportFragmentManager?.let { fragmentManager ->
|
||||||
val dialog = NodeSelectionBottomSheetDialog()
|
val dialog = NodeSelectionBottomSheetDialog()
|
||||||
|
@ -240,13 +290,7 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
|
||||||
}
|
}
|
||||||
|
|
||||||
useBundledTor?.setOnCheckedChangeListener { _, isChecked ->
|
useBundledTor?.setOnCheckedChangeListener { _, isChecked ->
|
||||||
walletProxyPortEditText?.visibility = if (isChecked) View.GONE else View.VISIBLE
|
if(!isChecked) {
|
||||||
walletProxyAddressEditText?.visibility = if (isChecked) View.GONE else View.VISIBLE
|
|
||||||
|
|
||||||
if(isChecked) {
|
|
||||||
ProxyService.instance?.samouraiTorManager?.start()
|
|
||||||
} else {
|
|
||||||
ProxyService.instance?.samouraiTorManager?.stop()
|
|
||||||
mViewModel?.setProxyAddress("")
|
mViewModel?.setProxyAddress("")
|
||||||
mViewModel?.setProxyPort("")
|
mViewModel?.setProxyPort("")
|
||||||
}
|
}
|
||||||
|
@ -270,11 +314,10 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
|
||||||
walletSeed: String,
|
walletSeed: String,
|
||||||
restoreHeightText: String
|
restoreHeightText: String
|
||||||
) {
|
) {
|
||||||
val activity: Activity? = activity
|
activity?.let { act ->
|
||||||
if (activity != null) {
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
mViewModel?.createOrImportWallet(
|
mViewModel?.createOrImportWallet(
|
||||||
activity,
|
act,
|
||||||
walletSeed,
|
walletSeed,
|
||||||
restoreHeightText,
|
restoreHeightText,
|
||||||
useOffset
|
useOffset
|
||||||
|
@ -288,10 +331,9 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
|
||||||
selectNodeButton?.text = getString(R.string.node_button_text, node?.address)
|
selectNodeButton?.text = getString(R.string.node_button_text, node?.address)
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
activity,
|
activity,
|
||||||
getString(R.string.node_selected),
|
getString(R.string.node_selected, node?.name ?: node?.host),
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
refreshProxy()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClickedEditNode(node: Node?) {}
|
override fun onClickedEditNode(node: Node?) {}
|
||||||
|
@ -310,10 +352,4 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
|
||||||
dialog.show(fragmentManager, "node_selection_dialog")
|
dialog.show(fragmentManager, "node_selection_dialog")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshProxy() {
|
|
||||||
val proxyAddress = walletProxyAddressEditText?.text.toString()
|
|
||||||
val proxyPort = walletProxyPortEditText?.text.toString()
|
|
||||||
ProxyService.instance?.updateProxy(proxyAddress, proxyPort)
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package net.mynero.wallet.fragment.onboarding
|
package net.mynero.wallet.fragment.onboarding
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.util.Patterns
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
@ -9,7 +8,7 @@ import androidx.lifecycle.ViewModel
|
||||||
import net.mynero.wallet.MainActivity
|
import net.mynero.wallet.MainActivity
|
||||||
import net.mynero.wallet.MoneroApplication
|
import net.mynero.wallet.MoneroApplication
|
||||||
import net.mynero.wallet.R
|
import net.mynero.wallet.R
|
||||||
import net.mynero.wallet.livedata.combineLatestIgnoreNull
|
import net.mynero.wallet.livedata.combineLiveDatas
|
||||||
import net.mynero.wallet.model.Wallet
|
import net.mynero.wallet.model.Wallet
|
||||||
import net.mynero.wallet.model.WalletManager
|
import net.mynero.wallet.model.WalletManager
|
||||||
import net.mynero.wallet.service.PrefService
|
import net.mynero.wallet.service.PrefService
|
||||||
|
@ -30,11 +29,19 @@ class OnboardingViewModel : ViewModel() {
|
||||||
private val _useBundledTor = MutableLiveData(false)
|
private val _useBundledTor = MutableLiveData(false)
|
||||||
val useBundledTor: LiveData<Boolean> = _useBundledTor
|
val useBundledTor: LiveData<Boolean> = _useBundledTor
|
||||||
private val _passphrase = MutableLiveData("")
|
private val _passphrase = MutableLiveData("")
|
||||||
|
val passphrase: LiveData<String> = _passphrase
|
||||||
private val _confirmedPassphrase = MutableLiveData("")
|
private val _confirmedPassphrase = MutableLiveData("")
|
||||||
|
private val _showMonerochan = MutableLiveData(true)
|
||||||
|
val showMonerochan: LiveData<Boolean> = _showMonerochan
|
||||||
var showMoreOptions: LiveData<Boolean> = _showMoreOptions
|
var showMoreOptions: LiveData<Boolean> = _showMoreOptions
|
||||||
var seedType: LiveData<SeedType> = _seedType
|
var seedType: LiveData<SeedType> = _seedType
|
||||||
|
|
||||||
val enableButton = combineLatestIgnoreNull(
|
init {
|
||||||
|
_useProxy.value = ProxyService.instance?.usingProxy
|
||||||
|
_useBundledTor.value = ProxyService.instance?.useBundledTor
|
||||||
|
}
|
||||||
|
|
||||||
|
val enableButton = combineLiveDatas(
|
||||||
seedType,
|
seedType,
|
||||||
_useProxy,
|
_useProxy,
|
||||||
_proxyAddress,
|
_proxyAddress,
|
||||||
|
@ -44,14 +51,14 @@ class OnboardingViewModel : ViewModel() {
|
||||||
_confirmedPassphrase,
|
_confirmedPassphrase,
|
||||||
_creatingWallet
|
_creatingWallet
|
||||||
) { seedType, useProxy, proxyAddress, proxyPort, useBundledTor, passphrase, confirmedPassphrase, creatingWallet ->
|
) { seedType, useProxy, proxyAddress, proxyPort, useBundledTor, passphrase, confirmedPassphrase, creatingWallet ->
|
||||||
if(seedType == null || useProxy == null || proxyAddress == null || proxyPort == null || useBundledTor == null || passphrase == null || confirmedPassphrase == null || creatingWallet == null) return@combineLatestIgnoreNull false
|
if(seedType == null || useProxy == null || proxyAddress == null || proxyPort == null || useBundledTor == null || passphrase == null || confirmedPassphrase == null || creatingWallet == null) return@combineLiveDatas false
|
||||||
if((passphrase.isNotEmpty() || confirmedPassphrase.isNotEmpty()) && passphrase != confirmedPassphrase) return@combineLatestIgnoreNull false
|
if((passphrase.isNotEmpty() || confirmedPassphrase.isNotEmpty()) && passphrase != confirmedPassphrase) return@combineLiveDatas false
|
||||||
if(creatingWallet) return@combineLatestIgnoreNull false
|
if(creatingWallet) return@combineLiveDatas false
|
||||||
if(seedType == SeedType.POLYSEED && passphrase.isEmpty()) return@combineLatestIgnoreNull false
|
if(seedType == SeedType.POLYSEED && (passphrase.isEmpty() || confirmedPassphrase.isEmpty())) return@combineLiveDatas false
|
||||||
if(useProxy && (proxyAddress.isEmpty() || proxyPort.isEmpty())) return@combineLatestIgnoreNull false
|
if(useProxy && (proxyAddress.isEmpty() || proxyPort.isEmpty())) return@combineLiveDatas false
|
||||||
if(useBundledTor && (proxyAddress.isEmpty() || proxyPort.isEmpty())) return@combineLatestIgnoreNull false
|
if(useBundledTor && (proxyAddress.isEmpty() || proxyPort.isEmpty())) return@combineLiveDatas false
|
||||||
|
|
||||||
return@combineLatestIgnoreNull true
|
return@combineLiveDatas true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onMoreOptionsClicked() {
|
fun onMoreOptionsClicked() {
|
||||||
|
@ -72,7 +79,6 @@ class OnboardingViewModel : ViewModel() {
|
||||||
) {
|
) {
|
||||||
val passphrase = _passphrase.value ?: return
|
val passphrase = _passphrase.value ?: return
|
||||||
val confirmedPassphrase = _confirmedPassphrase.value ?: return
|
val confirmedPassphrase = _confirmedPassphrase.value ?: return
|
||||||
val useProxy = _useProxy.value ?: return
|
|
||||||
|
|
||||||
val application = mainActivity.application as MoneroApplication
|
val application = mainActivity.application as MoneroApplication
|
||||||
_creatingWallet.postValue(true)
|
_creatingWallet.postValue(true)
|
||||||
|
@ -172,15 +178,6 @@ class OnboardingViewModel : ViewModel() {
|
||||||
val ok = walletStatus?.isOk
|
val ok = walletStatus?.isOk
|
||||||
walletFile.delete() // cache is broken for some reason when recovering wallets. delete the file here. this happens in monerujo too.
|
walletFile.delete() // cache is broken for some reason when recovering wallets. delete the file here. this happens in monerujo too.
|
||||||
if (ok == true) {
|
if (ok == true) {
|
||||||
var editor = PrefService.instance?.edit()
|
|
||||||
?.putBoolean(Constants.PREF_USE_BUNDLED_TOR, _useBundledTor.value == true)
|
|
||||||
?.putBoolean(Constants.PREF_USES_PROXY, useProxy)
|
|
||||||
if(useProxy) {
|
|
||||||
editor = editor?.putString(Constants.PREF_PROXY, "${_proxyAddress.value}:${_proxyPort.value}")
|
|
||||||
}
|
|
||||||
|
|
||||||
editor?.apply()
|
|
||||||
|
|
||||||
(mainActivity as MainActivity).init(walletFile, passphrase)
|
(mainActivity as MainActivity).init(walletFile, passphrase)
|
||||||
mainActivity.runOnUiThread { mainActivity.onBackPressed() }
|
mainActivity.runOnUiThread { mainActivity.onBackPressed() }
|
||||||
} else {
|
} else {
|
||||||
|
@ -228,18 +225,42 @@ class OnboardingViewModel : ViewModel() {
|
||||||
|
|
||||||
fun setProxyAddress(address: String) {
|
fun setProxyAddress(address: String) {
|
||||||
_proxyAddress.value = address
|
_proxyAddress.value = address
|
||||||
|
val port = _proxyPort.value ?: return
|
||||||
|
val proxyAddress = "$address:$port"
|
||||||
|
if(proxyAddress == ":") return
|
||||||
|
PrefService.instance?.edit()?.putString(Constants.PREF_PROXY, proxyAddress)?.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setProxyPort(port: String) {
|
fun setProxyPort(port: String) {
|
||||||
_proxyPort.value = port
|
_proxyPort.value = port
|
||||||
|
val address = _proxyAddress.value ?: return
|
||||||
|
val proxyAddress = "$address:$port"
|
||||||
|
if(proxyAddress == ":") return
|
||||||
|
PrefService.instance?.edit()?.putString(Constants.PREF_PROXY, proxyAddress)?.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setUseBundledTor(useBundled: Boolean) {
|
fun setUseBundledTor(useBundled: Boolean) {
|
||||||
_useBundledTor.value = useBundled
|
_useBundledTor.value = useBundled
|
||||||
|
PrefService.instance?.edit()?.putBoolean(Constants.PREF_USE_BUNDLED_TOR, useBundled)?.apply()
|
||||||
|
|
||||||
|
val samouraiTorManager = ProxyService.instance?.samouraiTorManager
|
||||||
|
if(useBundled && useProxy.value == true) {
|
||||||
|
samouraiTorManager?.start()
|
||||||
|
} else {
|
||||||
|
samouraiTorManager?.stop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setUseProxy(useProxy: Boolean) {
|
fun setUseProxy(useProxy: Boolean) {
|
||||||
_useProxy.value = useProxy
|
_useProxy.value = useProxy
|
||||||
|
PrefService.instance?.edit()?.putBoolean(Constants.PREF_USES_PROXY, useProxy)?.apply()
|
||||||
|
|
||||||
|
val samouraiTorManager = ProxyService.instance?.samouraiTorManager
|
||||||
|
if(useProxy && useBundledTor.value == true) {
|
||||||
|
samouraiTorManager?.start()
|
||||||
|
} else {
|
||||||
|
samouraiTorManager?.stop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setPassphrase(passphrase: String) {
|
fun setPassphrase(passphrase: String) {
|
||||||
|
@ -250,6 +271,11 @@ class OnboardingViewModel : ViewModel() {
|
||||||
_confirmedPassphrase.value = confirmedPassphrase
|
_confirmedPassphrase.value = confirmedPassphrase
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setMonerochan(b: Boolean) {
|
||||||
|
_showMonerochan.value = b
|
||||||
|
PrefService.instance?.edit()?.putBoolean(Constants.PREF_MONEROCHAN, b)?.apply()
|
||||||
|
}
|
||||||
|
|
||||||
enum class SeedType(val descResId: Int) {
|
enum class SeedType(val descResId: Int) {
|
||||||
LEGACY(R.string.seed_desc_legacy), POLYSEED(R.string.seed_desc_polyseed), UNKNOWN(0)
|
LEGACY(R.string.seed_desc_legacy), POLYSEED(R.string.seed_desc_polyseed), UNKNOWN(0)
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ import android.widget.Button
|
||||||
import android.widget.CheckBox
|
import android.widget.CheckBox
|
||||||
import android.widget.CompoundButton
|
import android.widget.CompoundButton
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.Switch
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.appcompat.widget.SwitchCompat
|
import androidx.appcompat.widget.SwitchCompat
|
||||||
|
@ -17,6 +19,7 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
import net.mynero.wallet.R
|
import net.mynero.wallet.R
|
||||||
import net.mynero.wallet.data.Node
|
import net.mynero.wallet.data.Node
|
||||||
import net.mynero.wallet.data.Node.Companion.fromJson
|
import net.mynero.wallet.data.Node.Companion.fromJson
|
||||||
|
@ -29,6 +32,7 @@ import net.mynero.wallet.fragment.dialog.NodeSelectionBottomSheetDialog.NodeSele
|
||||||
import net.mynero.wallet.fragment.dialog.PasswordBottomSheetDialog
|
import net.mynero.wallet.fragment.dialog.PasswordBottomSheetDialog
|
||||||
import net.mynero.wallet.fragment.dialog.PasswordBottomSheetDialog.PasswordListener
|
import net.mynero.wallet.fragment.dialog.PasswordBottomSheetDialog.PasswordListener
|
||||||
import net.mynero.wallet.fragment.dialog.WalletKeysBottomSheetDialog
|
import net.mynero.wallet.fragment.dialog.WalletKeysBottomSheetDialog
|
||||||
|
import net.mynero.wallet.model.EnumTorState
|
||||||
import net.mynero.wallet.service.BalanceService
|
import net.mynero.wallet.service.BalanceService
|
||||||
import net.mynero.wallet.service.HistoryService
|
import net.mynero.wallet.service.HistoryService
|
||||||
import net.mynero.wallet.service.PrefService
|
import net.mynero.wallet.service.PrefService
|
||||||
|
@ -44,6 +48,14 @@ class SettingsFragment : Fragment(), PasswordListener, NodeSelectionDialogListen
|
||||||
private var selectNodeButton: Button? = null
|
private var selectNodeButton: Button? = null
|
||||||
private var cachedProxyAddress: String = ""
|
private var cachedProxyAddress: String = ""
|
||||||
private var cachedProxyPort: String = ""
|
private var cachedProxyPort: String = ""
|
||||||
|
private var streetModeSwitch: SwitchCompat? = null
|
||||||
|
private var monerochanSwitch: SwitchCompat? = null
|
||||||
|
private var donationSwitch: SwitchCompat? = null
|
||||||
|
private var useBundledTor: CheckBox? = null
|
||||||
|
private var displaySeedButton: Button? = null
|
||||||
|
private var displayUtxosButton: Button? = null
|
||||||
|
private var torSwitch: SwitchCompat? = null
|
||||||
|
private var proxySettingsLayout: ConstraintLayout? = null
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
@ -55,68 +67,76 @@ class SettingsFragment : Fragment(), PasswordListener, NodeSelectionDialogListen
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
mViewModel = ViewModelProvider(this)[SettingsViewModel::class.java]
|
mViewModel = ViewModelProvider(this)[SettingsViewModel::class.java]
|
||||||
val displaySeedButton = view.findViewById<Button>(R.id.display_seed_button)
|
displaySeedButton = view.findViewById(R.id.display_seed_button)
|
||||||
val displayUtxosButton = view.findViewById<Button>(R.id.display_utxos_button)
|
displayUtxosButton = view.findViewById(R.id.display_utxos_button)
|
||||||
selectNodeButton = view.findViewById(R.id.select_node_button)
|
selectNodeButton = view.findViewById(R.id.select_node_button)
|
||||||
val streetModeSwitch = view.findViewById<SwitchCompat>(R.id.street_mode_switch)
|
streetModeSwitch = view.findViewById(R.id.street_mode_switch)
|
||||||
val monerochanSwitch = view.findViewById<SwitchCompat>(R.id.monerochan_switch)
|
monerochanSwitch = view.findViewById(R.id.monerochan_switch)
|
||||||
val donationSwitch = view.findViewById<SwitchCompat>(R.id.donate_per_tx_switch)
|
donationSwitch = view.findViewById(R.id.donate_per_tx_switch)
|
||||||
val torSwitch = view.findViewById<SwitchCompat>(R.id.tor_switch)
|
torSwitch = view.findViewById(R.id.tor_switch)
|
||||||
val proxySettingsLayout =
|
proxySettingsLayout = view.findViewById(R.id.wallet_proxy_settings_layout)
|
||||||
view.findViewById<ConstraintLayout>(R.id.wallet_proxy_settings_layout)
|
|
||||||
walletProxyAddressEditText = view.findViewById(R.id.wallet_proxy_address_edittext)
|
walletProxyAddressEditText = view.findViewById(R.id.wallet_proxy_address_edittext)
|
||||||
walletProxyPortEditText = view.findViewById(R.id.wallet_proxy_port_edittext)
|
walletProxyPortEditText = view.findViewById(R.id.wallet_proxy_port_edittext)
|
||||||
val useBundledTor = view.findViewById<CheckBox>(R.id.bundled_tor_checkbox)
|
useBundledTor = view.findViewById(R.id.bundled_tor_checkbox)
|
||||||
|
|
||||||
useBundledTor.isChecked = ProxyService.instance?.useBundledTor == true
|
useBundledTor?.isChecked = ProxyService.instance?.useBundledTor == true
|
||||||
walletProxyPortEditText?.visibility = if (useBundledTor.isChecked) View.GONE else View.VISIBLE
|
walletProxyPortEditText?.visibility = if (useBundledTor?.isChecked == true) View.GONE else View.VISIBLE
|
||||||
walletProxyAddressEditText?.visibility = if (useBundledTor.isChecked) View.GONE else View.VISIBLE
|
walletProxyAddressEditText?.visibility = if (useBundledTor?.isChecked == true) View.GONE else View.VISIBLE
|
||||||
|
streetModeSwitch?.isChecked = PrefService.instance?.getBoolean(Constants.PREF_STREET_MODE, false) == true
|
||||||
|
monerochanSwitch?.isChecked = PrefService.instance?.getBoolean(Constants.PREF_MONEROCHAN, true) == true
|
||||||
|
donationSwitch?.isChecked = PrefService.instance?.getBoolean(Constants.PREF_DONATE_PER_TX, false) == true
|
||||||
|
|
||||||
streetModeSwitch.isChecked =
|
|
||||||
PrefService.instance?.getBoolean(Constants.PREF_STREET_MODE, false) == true
|
|
||||||
streetModeSwitch.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
|
||||||
PrefService.instance?.edit()?.putBoolean(Constants.PREF_STREET_MODE, b)?.apply()
|
|
||||||
BalanceService.instance?.refreshBalance()
|
|
||||||
}
|
|
||||||
monerochanSwitch.isChecked =
|
|
||||||
PrefService.instance?.getBoolean(Constants.PREF_MONEROCHAN, true) == true
|
|
||||||
monerochanSwitch.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
|
||||||
PrefService.instance?.edit()?.putBoolean(Constants.PREF_MONEROCHAN, b)?.apply()
|
|
||||||
HistoryService.instance?.refreshHistory()
|
|
||||||
}
|
|
||||||
donationSwitch.isChecked =
|
|
||||||
PrefService.instance?.getBoolean(Constants.PREF_DONATE_PER_TX, false) == true
|
|
||||||
donationSwitch.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
|
||||||
PrefService.instance?.edit()?.putBoolean(Constants.PREF_DONATE_PER_TX, b)?.apply()
|
|
||||||
}
|
|
||||||
val prefService = PrefService.instance ?: return
|
|
||||||
val usesProxy = ProxyService.instance?.usingProxy == true
|
val usesProxy = ProxyService.instance?.usingProxy == true
|
||||||
cachedProxyAddress = ProxyService.instance?.proxyAddress ?: return
|
cachedProxyAddress = ProxyService.instance?.proxyAddress ?: return
|
||||||
cachedProxyPort = ProxyService.instance?.proxyPort ?: return
|
cachedProxyPort = ProxyService.instance?.proxyPort ?: return
|
||||||
if (ProxyService.instance?.hasProxySet() == true) {
|
if (ProxyService.instance?.hasProxySet() == true) {
|
||||||
initProxyStuff(cachedProxyAddress, cachedProxyPort)
|
initProxyStuff(cachedProxyAddress, cachedProxyPort)
|
||||||
}
|
}
|
||||||
torSwitch.isChecked = usesProxy
|
torSwitch?.isChecked = usesProxy
|
||||||
if (usesProxy) {
|
proxySettingsLayout?.visibility = if (usesProxy) View.VISIBLE else View.GONE
|
||||||
proxySettingsLayout.visibility = View.VISIBLE
|
val node = PrefService.instance?.node // shouldn't use default value here
|
||||||
} else {
|
selectNodeButton?.text = getString(R.string.node_button_text, node?.address)
|
||||||
proxySettingsLayout.visibility = View.GONE
|
|
||||||
}
|
bindListeners()
|
||||||
torSwitch.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
bindObservers()
|
||||||
prefService.edit()?.putBoolean(Constants.PREF_USES_PROXY, b)?.apply()
|
}
|
||||||
if (b) {
|
|
||||||
if (ProxyService.instance?.hasProxySet() == true) {
|
private fun bindListeners() {
|
||||||
val proxyAddress = ProxyService.instance?.proxyAddress ?: return@setOnCheckedChangeListener
|
val onBackPressedCallback: OnBackPressedCallback = object : OnBackPressedCallback(true) {
|
||||||
val proxyPort = ProxyService.instance?.proxyPort ?: return@setOnCheckedChangeListener
|
override fun handleOnBackPressed() {
|
||||||
initProxyStuff(proxyAddress, proxyPort)
|
refreshProxy()
|
||||||
}
|
findNavController().popBackStack()
|
||||||
proxySettingsLayout.visibility = View.VISIBLE
|
|
||||||
} else {
|
|
||||||
proxySettingsLayout.visibility = View.GONE
|
|
||||||
}
|
}
|
||||||
refreshProxy()
|
|
||||||
}
|
}
|
||||||
displaySeedButton.setOnClickListener {
|
activity?.onBackPressedDispatcher?.addCallback(viewLifecycleOwner, onBackPressedCallback)
|
||||||
|
|
||||||
|
donationSwitch?.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
||||||
|
PrefService.instance?.edit()?.putBoolean(Constants.PREF_DONATE_PER_TX, b)?.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
streetModeSwitch?.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
||||||
|
PrefService.instance?.edit()?.putBoolean(Constants.PREF_STREET_MODE, b)?.apply()
|
||||||
|
BalanceService.instance?.refreshBalance()
|
||||||
|
}
|
||||||
|
|
||||||
|
monerochanSwitch?.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
||||||
|
PrefService.instance?.edit()?.putBoolean(Constants.PREF_MONEROCHAN, b)?.apply()
|
||||||
|
HistoryService.instance?.refreshHistory()
|
||||||
|
}
|
||||||
|
|
||||||
|
selectNodeButton?.setOnClickListener {
|
||||||
|
activity?.supportFragmentManager?.let { fragmentManager ->
|
||||||
|
val dialog = NodeSelectionBottomSheetDialog()
|
||||||
|
dialog.listener = this
|
||||||
|
dialog.show(fragmentManager, "node_selection_dialog")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useBundledTor?.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
mViewModel?.setUseBundledTor(isChecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
displaySeedButton?.setOnClickListener {
|
||||||
val usesPassword =
|
val usesPassword =
|
||||||
PrefService.instance?.getBoolean(Constants.PREF_USES_PASSWORD, false) == true
|
PrefService.instance?.getBoolean(Constants.PREF_USES_PASSWORD, false) == true
|
||||||
if (usesPassword) {
|
if (usesPassword) {
|
||||||
|
@ -130,37 +150,66 @@ class SettingsFragment : Fragment(), PasswordListener, NodeSelectionDialogListen
|
||||||
displaySeedDialog("")
|
displaySeedDialog("")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
displayUtxosButton.setOnClickListener { navigate(R.id.nav_to_utxos) }
|
|
||||||
val node = PrefService.instance?.node // shouldn't use default value here
|
displayUtxosButton?.setOnClickListener { navigate(R.id.nav_to_utxos) }
|
||||||
selectNodeButton?.text = getString(R.string.node_button_text, node?.address)
|
|
||||||
selectNodeButton?.setOnClickListener {
|
torSwitch?.setOnCheckedChangeListener { _: CompoundButton?, b: Boolean ->
|
||||||
activity?.supportFragmentManager?.let { fragmentManager ->
|
mViewModel?.setUseProxy(b)
|
||||||
val dialog = NodeSelectionBottomSheetDialog()
|
}
|
||||||
dialog.listener = this
|
}
|
||||||
dialog.show(fragmentManager, "node_selection_dialog")
|
|
||||||
|
private fun bindObservers() {
|
||||||
|
mViewModel?.useProxy?.observe(viewLifecycleOwner) { b ->
|
||||||
|
if (b) {
|
||||||
|
if (ProxyService.instance?.hasProxySet() == true) {
|
||||||
|
val proxyAddress = ProxyService.instance?.proxyAddress ?: return@observe
|
||||||
|
val proxyPort = ProxyService.instance?.proxyPort ?: return@observe
|
||||||
|
initProxyStuff(proxyAddress, proxyPort)
|
||||||
|
}
|
||||||
|
proxySettingsLayout?.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
proxySettingsLayout?.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
refreshProxy()
|
||||||
}
|
}
|
||||||
|
|
||||||
useBundledTor?.setOnCheckedChangeListener { _, isChecked ->
|
mViewModel?.useBundledTor?.observe(viewLifecycleOwner) { isChecked ->
|
||||||
walletProxyPortEditText?.visibility = if (isChecked) View.GONE else View.VISIBLE
|
walletProxyPortEditText?.visibility = if (isChecked) View.GONE else View.VISIBLE
|
||||||
walletProxyAddressEditText?.visibility = if (isChecked) View.GONE else View.VISIBLE
|
walletProxyAddressEditText?.visibility = if (isChecked) View.GONE else View.VISIBLE
|
||||||
PrefService.instance?.edit()?.putBoolean(Constants.PREF_USE_BUNDLED_TOR, isChecked)?.apply()
|
|
||||||
|
|
||||||
if(isChecked) {
|
|
||||||
ProxyService.instance?.samouraiTorManager?.start()
|
|
||||||
} else {
|
|
||||||
ProxyService.instance?.samouraiTorManager?.stop()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val onBackPressedCallback: OnBackPressedCallback = object : OnBackPressedCallback(true) {
|
val samouraiTorManager = ProxyService.instance?.samouraiTorManager
|
||||||
override fun handleOnBackPressed() {
|
val indicatorCircle = view?.findViewById<CircularProgressIndicator>(R.id.settings_tor_loading_progressindicator)
|
||||||
refreshProxy()
|
val torIcon = view?.findViewById<ImageView>(R.id.settings_tor_icon)
|
||||||
findNavController().popBackStack()
|
|
||||||
|
samouraiTorManager?.getTorStateLiveData()?.observe(viewLifecycleOwner) { state ->
|
||||||
|
samouraiTorManager.getProxy()?.address()?.let { socketAddress ->
|
||||||
|
if(socketAddress.toString().isEmpty()) return@let
|
||||||
|
if(mViewModel?.useProxy?.value == true && mViewModel?.useBundledTor?.value == true) {
|
||||||
|
torIcon?.visibility = View.VISIBLE
|
||||||
|
indicatorCircle?.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
indicatorCircle?.isIndeterminate = state.progressIndicator == 0
|
||||||
|
indicatorCircle?.progress = state.progressIndicator
|
||||||
|
|
||||||
|
when (state.state) {
|
||||||
|
EnumTorState.OFF -> {
|
||||||
|
torIcon?.visibility = View.INVISIBLE
|
||||||
|
indicatorCircle?.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
EnumTorState.STARTING -> {
|
||||||
|
torIcon?.visibility = View.INVISIBLE
|
||||||
|
indicatorCircle?.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
EnumTorState.STOPPING -> {
|
||||||
|
torIcon?.visibility = View.INVISIBLE
|
||||||
|
indicatorCircle?.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activity?.onBackPressedDispatcher?.addCallback(viewLifecycleOwner, onBackPressedCallback)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshProxy() {
|
private fun refreshProxy() {
|
||||||
|
|
|
@ -1,12 +1,47 @@
|
||||||
package net.mynero.wallet.fragment.settings
|
package net.mynero.wallet.fragment.settings
|
||||||
|
|
||||||
import android.util.Patterns
|
import android.util.Patterns
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import net.mynero.wallet.MoneroApplication
|
import net.mynero.wallet.MoneroApplication
|
||||||
import net.mynero.wallet.model.WalletManager
|
import net.mynero.wallet.model.WalletManager
|
||||||
import net.mynero.wallet.service.PrefService
|
import net.mynero.wallet.service.PrefService
|
||||||
|
import net.mynero.wallet.service.ProxyService
|
||||||
import net.mynero.wallet.util.Constants
|
import net.mynero.wallet.util.Constants
|
||||||
|
|
||||||
class SettingsViewModel : ViewModel() {
|
class SettingsViewModel : ViewModel() {
|
||||||
|
private val _useProxy = MutableLiveData(false)
|
||||||
|
val useProxy: LiveData<Boolean> = _useProxy
|
||||||
|
private val _useBundledTor = MutableLiveData(false)
|
||||||
|
val useBundledTor: LiveData<Boolean> = _useBundledTor
|
||||||
|
|
||||||
|
init {
|
||||||
|
_useProxy.value = ProxyService.instance?.usingProxy
|
||||||
|
_useBundledTor.value = ProxyService.instance?.useBundledTor
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setUseProxy(use: Boolean) {
|
||||||
|
_useProxy.value = use
|
||||||
|
PrefService.instance?.edit()?.putBoolean(Constants.PREF_USES_PROXY, use)?.apply()
|
||||||
|
|
||||||
|
val samouraiTorManager = ProxyService.instance?.samouraiTorManager
|
||||||
|
if(use && useBundledTor.value == true) {
|
||||||
|
samouraiTorManager?.start()
|
||||||
|
} else {
|
||||||
|
samouraiTorManager?.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setUseBundledTor(use: Boolean) {
|
||||||
|
PrefService.instance?.edit()?.putBoolean(Constants.PREF_USE_BUNDLED_TOR, use)?.apply()
|
||||||
|
_useBundledTor.value = use
|
||||||
|
|
||||||
|
val samouraiTorManager = ProxyService.instance?.samouraiTorManager
|
||||||
|
if(use && useProxy.value == true) {
|
||||||
|
samouraiTorManager?.start()
|
||||||
|
} else {
|
||||||
|
samouraiTorManager?.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
package net.mynero.wallet.livedata
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MediatorLiveData
|
||||||
|
|
||||||
|
fun <T1, T2, T3, T4, T5, T6, T7, T8, S> combineLiveDatas(
|
||||||
|
source1: LiveData<T1>,
|
||||||
|
source2: LiveData<T2>,
|
||||||
|
source3: LiveData<T3>,
|
||||||
|
source4: LiveData<T4>,
|
||||||
|
source5: LiveData<T5>,
|
||||||
|
source6: LiveData<T6>,
|
||||||
|
source7: LiveData<T7>,
|
||||||
|
source8: LiveData<T8>,
|
||||||
|
func: (T1?, T2?, T3?, T4?, T5?, T6?, T7?, T8?) -> S?
|
||||||
|
): LiveData<S> {
|
||||||
|
val result = MediatorLiveData<S>()
|
||||||
|
result.addSource(source1) {
|
||||||
|
func(
|
||||||
|
source1.value,
|
||||||
|
source2.value,
|
||||||
|
source3.value,
|
||||||
|
source4.value,
|
||||||
|
source5.value,
|
||||||
|
source6.value,
|
||||||
|
source7.value,
|
||||||
|
source8.value
|
||||||
|
)?.run { result.value = this }
|
||||||
|
}
|
||||||
|
|
||||||
|
result.addSource(source2) {
|
||||||
|
func(
|
||||||
|
source1.value,
|
||||||
|
source2.value,
|
||||||
|
source3.value,
|
||||||
|
source4.value,
|
||||||
|
source5.value,
|
||||||
|
source6.value,
|
||||||
|
source7.value,
|
||||||
|
source8.value
|
||||||
|
)?.run { result.value = this }
|
||||||
|
}
|
||||||
|
|
||||||
|
result.addSource(source3) {
|
||||||
|
func(
|
||||||
|
source1.value,
|
||||||
|
source2.value,
|
||||||
|
source3.value,
|
||||||
|
source4.value,
|
||||||
|
source5.value,
|
||||||
|
source6.value,
|
||||||
|
source7.value,
|
||||||
|
source8.value
|
||||||
|
)?.run { result.value = this }
|
||||||
|
}
|
||||||
|
|
||||||
|
result.addSource(source4) {
|
||||||
|
func(
|
||||||
|
source1.value,
|
||||||
|
source2.value,
|
||||||
|
source3.value,
|
||||||
|
source4.value,
|
||||||
|
source5.value,
|
||||||
|
source6.value,
|
||||||
|
source7.value,
|
||||||
|
source8.value
|
||||||
|
)?.run { result.value = this }
|
||||||
|
}
|
||||||
|
|
||||||
|
result.addSource(source5) {
|
||||||
|
func(
|
||||||
|
source1.value,
|
||||||
|
source2.value,
|
||||||
|
source3.value,
|
||||||
|
source4.value,
|
||||||
|
source5.value,
|
||||||
|
source6.value,
|
||||||
|
source7.value,
|
||||||
|
source8.value
|
||||||
|
)?.run { result.value = this }
|
||||||
|
}
|
||||||
|
|
||||||
|
result.addSource(source6) {
|
||||||
|
func(
|
||||||
|
source1.value,
|
||||||
|
source2.value,
|
||||||
|
source3.value,
|
||||||
|
source4.value,
|
||||||
|
source5.value,
|
||||||
|
source6.value,
|
||||||
|
source7.value,
|
||||||
|
source8.value
|
||||||
|
)?.run { result.value = this }
|
||||||
|
}
|
||||||
|
|
||||||
|
result.addSource(source7) {
|
||||||
|
func(
|
||||||
|
source1.value,
|
||||||
|
source2.value,
|
||||||
|
source3.value,
|
||||||
|
source4.value,
|
||||||
|
source5.value,
|
||||||
|
source6.value,
|
||||||
|
source7.value,
|
||||||
|
source8.value
|
||||||
|
)?.run { result.value = this }
|
||||||
|
}
|
||||||
|
|
||||||
|
result.addSource(source8) {
|
||||||
|
func(
|
||||||
|
source1.value,
|
||||||
|
source2.value,
|
||||||
|
source3.value,
|
||||||
|
source4.value,
|
||||||
|
source5.value,
|
||||||
|
source6.value,
|
||||||
|
source7.value,
|
||||||
|
source8.value
|
||||||
|
)?.run { result.value = this }
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
|
@ -1,414 +0,0 @@
|
||||||
package net.mynero.wallet.livedata
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import androidx.lifecycle.MediatorLiveData
|
|
||||||
|
|
||||||
fun <T1, T2, S> combineLatest(
|
|
||||||
source1: LiveData<T1>,
|
|
||||||
source2: LiveData<T2>,
|
|
||||||
func: (T1?, T2?) -> S?
|
|
||||||
): LiveData<S> {
|
|
||||||
val result = MediatorLiveData<S>()
|
|
||||||
result.addSource(source1) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value)
|
|
||||||
}
|
|
||||||
result.addSource(source2) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T1, T2, T3, S> combineLatest(
|
|
||||||
source1: LiveData<T1>,
|
|
||||||
source2: LiveData<T2>,
|
|
||||||
source3: LiveData<T3>,
|
|
||||||
func: (T1?, T2?, T3?) -> S?
|
|
||||||
): LiveData<S> {
|
|
||||||
val result = MediatorLiveData<S>()
|
|
||||||
result.addSource(source1) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value, source3.value)
|
|
||||||
}
|
|
||||||
result.addSource(source2) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value, source3.value)
|
|
||||||
}
|
|
||||||
result.addSource(source3) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value, source3.value)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T1, T2, T3, T4, S> combineLatest(
|
|
||||||
source1: LiveData<T1>,
|
|
||||||
source2: LiveData<T2>,
|
|
||||||
source3: LiveData<T3>,
|
|
||||||
source4: LiveData<T4>,
|
|
||||||
func: (T1?, T2?, T3?, T4?) -> S?
|
|
||||||
): LiveData<S> {
|
|
||||||
val result = MediatorLiveData<S>()
|
|
||||||
result.addSource(source1) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value, source3.value, source4.value)
|
|
||||||
}
|
|
||||||
result.addSource(source2) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value, source3.value, source4.value)
|
|
||||||
}
|
|
||||||
result.addSource(source3) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value, source3.value, source4.value)
|
|
||||||
}
|
|
||||||
result.addSource(source4) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value, source3.value, source4.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T1, T2, T3, T4, T5, S> combineLatest(
|
|
||||||
source1: LiveData<T1>,
|
|
||||||
source2: LiveData<T2>,
|
|
||||||
source3: LiveData<T3>,
|
|
||||||
source4: LiveData<T4>,
|
|
||||||
source5: LiveData<T5>,
|
|
||||||
func: (T1?, T2?, T3?, T4?, T5?) -> S?
|
|
||||||
): LiveData<S> {
|
|
||||||
val result = MediatorLiveData<S>()
|
|
||||||
result.addSource(source1) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value, source3.value, source4.value, source5.value)
|
|
||||||
}
|
|
||||||
result.addSource(source2) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value, source3.value, source4.value, source5.value)
|
|
||||||
}
|
|
||||||
result.addSource(source3) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value, source3.value, source4.value, source5.value)
|
|
||||||
}
|
|
||||||
result.addSource(source4) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value, source3.value, source4.value, source5.value)
|
|
||||||
}
|
|
||||||
result.addSource(source5) {
|
|
||||||
result.value = func.invoke(source1.value, source2.value, source3.value, source4.value, source5.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T1, T2, S> combineLatestIgnoreNull(
|
|
||||||
source1: LiveData<T1>,
|
|
||||||
source2: LiveData<T2>,
|
|
||||||
func: (T1?, T2?) -> S?
|
|
||||||
): LiveData<S> {
|
|
||||||
val result = MediatorLiveData<S>()
|
|
||||||
result.addSource(source1) {
|
|
||||||
func.invoke(source1.value, source2.value)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
result.addSource(source2) {
|
|
||||||
func.invoke(source1.value, source2.value)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T1, T2, T3, S> combineLatestIgnoreNull(
|
|
||||||
source1: LiveData<T1>,
|
|
||||||
source2: LiveData<T2>,
|
|
||||||
source3: LiveData<T3>,
|
|
||||||
func: (T1?, T2?, T3?) -> S?
|
|
||||||
): LiveData<S> {
|
|
||||||
val result = MediatorLiveData<S>()
|
|
||||||
result.addSource(source1) {
|
|
||||||
func(source1.value, source2.value, source3.value)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source2) {
|
|
||||||
func(source1.value, source2.value, source3.value)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source3) {
|
|
||||||
func(source1.value, source2.value, source3.value)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T1, T2, T3, T4, S> combineLatestIgnoreNull(
|
|
||||||
source1: LiveData<T1>,
|
|
||||||
source2: LiveData<T2>,
|
|
||||||
source3: LiveData<T3>,
|
|
||||||
source4: LiveData<T4>,
|
|
||||||
func: (T1?, T2?, T3?, T4?) -> S?
|
|
||||||
): LiveData<S> {
|
|
||||||
val result = MediatorLiveData<S>()
|
|
||||||
result.addSource(source1) {
|
|
||||||
func(source1.value, source2.value, source3.value, source4.value)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source2) {
|
|
||||||
func(source1.value, source2.value, source3.value, source4.value)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source3) {
|
|
||||||
func(source1.value, source2.value, source3.value, source4.value)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source4) {
|
|
||||||
func(source1.value, source2.value, source3.value, source4.value)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T1, T2, T3, T4, T5, S> combineLatestIgnoreNull(
|
|
||||||
source1: LiveData<T1>,
|
|
||||||
source2: LiveData<T2>,
|
|
||||||
source3: LiveData<T3>,
|
|
||||||
source4: LiveData<T4>,
|
|
||||||
source5: LiveData<T5>,
|
|
||||||
func: (T1?, T2?, T3?, T4?, T5?) -> S?
|
|
||||||
): LiveData<S> {
|
|
||||||
val result = MediatorLiveData<S>()
|
|
||||||
result.addSource(source1) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source2) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source3) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source4) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source5) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T1, T2, T3, T4, T5, T6, S> combineLatestIgnoreNull(
|
|
||||||
source1: LiveData<T1>,
|
|
||||||
source2: LiveData<T2>,
|
|
||||||
source3: LiveData<T3>,
|
|
||||||
source4: LiveData<T4>,
|
|
||||||
source5: LiveData<T5>,
|
|
||||||
source6: LiveData<T6>,
|
|
||||||
func: (T1?, T2?, T3?, T4?, T5?, T6?) -> S?
|
|
||||||
): LiveData<S> {
|
|
||||||
val result = MediatorLiveData<S>()
|
|
||||||
result.addSource(source1) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source2) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source3) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source4) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source5) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source6) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T1, T2, T3, T4, T5, T6, T7, T8, S> combineLatestIgnoreNull(
|
|
||||||
source1: LiveData<T1>,
|
|
||||||
source2: LiveData<T2>,
|
|
||||||
source3: LiveData<T3>,
|
|
||||||
source4: LiveData<T4>,
|
|
||||||
source5: LiveData<T5>,
|
|
||||||
source6: LiveData<T6>,
|
|
||||||
source7: LiveData<T7>,
|
|
||||||
source8: LiveData<T8>,
|
|
||||||
func: (T1?, T2?, T3?, T4?, T5?, T6?, T7?, T8?) -> S?
|
|
||||||
): LiveData<S> {
|
|
||||||
val result = MediatorLiveData<S>()
|
|
||||||
result.addSource(source1) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value,
|
|
||||||
source7.value,
|
|
||||||
source8.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source2) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value,
|
|
||||||
source7.value,
|
|
||||||
source8.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source3) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value,
|
|
||||||
source7.value,
|
|
||||||
source8.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source4) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value,
|
|
||||||
source7.value,
|
|
||||||
source8.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source5) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value,
|
|
||||||
source7.value,
|
|
||||||
source8.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source6) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value,
|
|
||||||
source7.value,
|
|
||||||
source8.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source7) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value,
|
|
||||||
source7.value,
|
|
||||||
source8.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addSource(source8) {
|
|
||||||
func(
|
|
||||||
source1.value,
|
|
||||||
source2.value,
|
|
||||||
source3.value,
|
|
||||||
source4.value,
|
|
||||||
source5.value,
|
|
||||||
source6.value,
|
|
||||||
source7.value,
|
|
||||||
source8.value
|
|
||||||
)?.run { result.value = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
|
@ -17,10 +17,8 @@ class ProxyService(activity: MainActivity) : ServiceBase(null) {
|
||||||
|
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
samouraiTorManager?.getTorStateLiveData()?.observeForever {
|
samouraiTorManager?.getTorStateLiveData()?.observeForever {
|
||||||
println("STATE CHANGE:: ${it.state.name}")
|
|
||||||
samouraiTorManager?.getProxy()?.address()?.let { socketAddress ->
|
samouraiTorManager?.getProxy()?.address()?.let { socketAddress ->
|
||||||
if(socketAddress.toString().isEmpty()) return@let
|
if(socketAddress.toString().isEmpty()) return@let
|
||||||
println("PROXY INIT")
|
|
||||||
val proxyString = socketAddress.toString().substring(1)
|
val proxyString = socketAddress.toString().substring(1)
|
||||||
val address = proxyString.split(":")[0]
|
val address = proxyString.split(":")[0]
|
||||||
val port = proxyString.split(":")[1]
|
val port = proxyString.split(":")[1]
|
||||||
|
|
|
@ -23,17 +23,38 @@
|
||||||
android:paddingTop="24dp">
|
android:paddingTop="24dp">
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/create_wallet_textview"
|
android:id="@+id/create_wallet_textview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:text="@string/create_wallet"
|
android:text="@string/create_wallet"
|
||||||
android:textSize="32sp"
|
android:textSize="32sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constraintBottom_toTopOf="@id/wallet_password_edittext"
|
app:layout_constraintBottom_toTopOf="@id/wallet_password_edittext"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toStartOf="@id/onboarding_tor_loading_progressindicator"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/onboarding_tor_icon"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:src="@drawable/tor"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/onboarding_tor_loading_progressindicator"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/onboarding_tor_loading_progressindicator"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/onboarding_tor_loading_progressindicator"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/onboarding_tor_loading_progressindicator"/>
|
||||||
|
|
||||||
|
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
|
android:id="@+id/onboarding_tor_loading_progressindicator"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/create_wallet_textview"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/create_wallet_textview"/>
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/wallet_password_edittext"
|
android:id="@+id/wallet_password_edittext"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -248,7 +269,6 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
android:text="@string/use_bundled_tor"
|
android:text="@string/use_bundled_tor"
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintBottom_toTopOf="@id/wallet_proxy_address_edittext"
|
app:layout_constraintBottom_toTopOf="@id/wallet_proxy_address_edittext"
|
||||||
|
@ -260,7 +280,6 @@
|
||||||
android:background="@drawable/edittext_bg"
|
android:background="@drawable/edittext_bg"
|
||||||
android:hint="@string/wallet_proxy_address_hint"
|
android:hint="@string/wallet_proxy_address_hint"
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/wallet_proxy_port_edittext"
|
app:layout_constraintBottom_toTopOf="@id/wallet_proxy_port_edittext"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
@ -275,7 +294,6 @@
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|
|
@ -19,9 +19,29 @@
|
||||||
android:layout_marginEnd="24dp"
|
android:layout_marginEnd="24dp"
|
||||||
android:textSize="32sp"
|
android:textSize="32sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toStartOf="@id/settings_tor_loading_progressindicator"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/settings_tor_icon"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:src="@drawable/tor"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/settings_tor_loading_progressindicator"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/settings_tor_loading_progressindicator"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/settings_tor_loading_progressindicator"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/settings_tor_loading_progressindicator"/>
|
||||||
|
|
||||||
|
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
|
android:id="@+id/settings_tor_loading_progressindicator"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/settings_textview"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/settings_textview"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/wallet_settings_textview"
|
android:id="@+id/wallet_settings_textview"
|
||||||
|
|
Loading…
Reference in a new issue