More refactoring for built-in Tor changes and fixes

This commit is contained in:
pokkst 2023-12-09 04:21:14 -06:00
parent bd67d6d4bd
commit a128617342
No known key found for this signature in database
GPG key ID: EC4FAAA66859FAA4
14 changed files with 131 additions and 113 deletions

View file

@ -10,8 +10,8 @@ android {
applicationId "net.mynero.wallet" applicationId "net.mynero.wallet"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 34 targetSdkVersion 34
versionCode 50400 versionCode 50500
versionName "0.5.4 'Fluorine Fermi'" versionName "0.5.5 'Fluorine Fermi'"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild { externalNativeBuild {
cmake { cmake {

View file

@ -45,7 +45,6 @@ class MainActivity : AppCompatActivity(), MoneroHandlerThread.Listener, Password
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
ProxyService(this)
val walletFile = File(applicationInfo.dataDir, Constants.WALLET_NAME) val walletFile = File(applicationInfo.dataDir, Constants.WALLET_NAME)
val walletKeysFile = File(applicationInfo.dataDir, Constants.WALLET_NAME + ".keys") val walletKeysFile = File(applicationInfo.dataDir, Constants.WALLET_NAME + ".keys")
if (walletKeysFile.exists()) { if (walletKeysFile.exists()) {

View file

@ -2,6 +2,7 @@ package net.mynero.wallet
import android.app.Application import android.app.Application
import net.mynero.wallet.service.PrefService import net.mynero.wallet.service.PrefService
import net.mynero.wallet.service.ProxyService
import net.mynero.wallet.util.NightmodeHelper import net.mynero.wallet.util.NightmodeHelper
import java.util.concurrent.ExecutorService import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors import java.util.concurrent.Executors
@ -13,6 +14,7 @@ class MoneroApplication : Application() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
PrefService(this) PrefService(this)
ProxyService(this)
NightmodeHelper.preferredNightmode NightmodeHelper.preferredNightmode
executor = Executors.newFixedThreadPool(16) executor = Executors.newFixedThreadPool(16)
} }

View file

@ -1,6 +1,7 @@
package net.mynero.wallet.fragment.home package net.mynero.wallet.fragment.home
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -78,7 +79,7 @@ class HomeFragment : Fragment(), TxInfoAdapterListener {
ProxyService.instance?.proxyChangeEvents?.observe(viewLifecycleOwner) { proxy -> ProxyService.instance?.proxyChangeEvents?.observe(viewLifecycleOwner) { proxy ->
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
Timber.d("Updating proxy:: $proxy") Log.d("HomeFragment", "Updating proxy:: $proxy")
WalletManager.instance?.setProxy(proxy) WalletManager.instance?.setProxy(proxy)
WalletManager.instance?.wallet?.setProxy(proxy) WalletManager.instance?.wallet?.setProxy(proxy)
WalletManager.instance?.wallet?.init(0) WalletManager.instance?.wallet?.init(0)
@ -88,7 +89,7 @@ class HomeFragment : Fragment(), TxInfoAdapterListener {
DaemonService.instance?.daemonChangeEvents?.observe(viewLifecycleOwner) { daemon -> DaemonService.instance?.daemonChangeEvents?.observe(viewLifecycleOwner) { daemon ->
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
Timber.d("Updating daemon:: $daemon") Log.d("HomeFragment", "Updating daemon:: $daemon")
WalletManager.instance?.setDaemon(daemon) WalletManager.instance?.setDaemon(daemon)
WalletManager.instance?.wallet?.init(0) WalletManager.instance?.wallet?.init(0)
WalletManager.instance?.wallet?.setTrustedDaemon(daemon.trusted) WalletManager.instance?.wallet?.setTrustedDaemon(daemon.trusted)

View file

@ -169,12 +169,7 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
samouraiTorManager?.getTorStateLiveData()?.observe(viewLifecycleOwner) { state -> 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
val proxyString = socketAddress.toString().substring(1)
val address = proxyString.split(":")[0]
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?.setProxyPort(port)
torIcon?.visibility = View.VISIBLE torIcon?.visibility = View.VISIBLE
indicatorCircle?.visibility = View.INVISIBLE indicatorCircle?.visibility = View.INVISIBLE
} }
@ -188,11 +183,7 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
torIcon?.visibility = View.INVISIBLE torIcon?.visibility = View.INVISIBLE
indicatorCircle?.visibility = View.INVISIBLE indicatorCircle?.visibility = View.INVISIBLE
} }
EnumTorState.STARTING -> { EnumTorState.STARTING, EnumTorState.STOPPING -> {
torIcon?.visibility = View.INVISIBLE
indicatorCircle?.visibility = View.VISIBLE
}
EnumTorState.STOPPING -> {
torIcon?.visibility = View.INVISIBLE torIcon?.visibility = View.INVISIBLE
indicatorCircle?.visibility = View.VISIBLE indicatorCircle?.visibility = View.VISIBLE
} }
@ -290,11 +281,6 @@ class OnboardingFragment : Fragment(), NodeSelectionDialogListener, AddNodeListe
} }
useBundledTor?.setOnCheckedChangeListener { _, isChecked -> useBundledTor?.setOnCheckedChangeListener { _, isChecked ->
if(!isChecked) {
mViewModel?.setProxyAddress("")
mViewModel?.setProxyPort("")
}
mViewModel?.setUseBundledTor(isChecked) mViewModel?.setUseBundledTor(isChecked)
} }
} }

View file

@ -49,14 +49,16 @@ class OnboardingViewModel : ViewModel() {
_useBundledTor, _useBundledTor,
_passphrase, _passphrase,
_confirmedPassphrase, _confirmedPassphrase,
_creatingWallet _creatingWallet,
) { seedType, useProxy, proxyAddress, proxyPort, useBundledTor, passphrase, confirmedPassphrase, creatingWallet -> ProxyService.instance?.samouraiTorManager?.getTorStateLiveData()
) { seedType, useProxy, proxyAddress, proxyPort, useBundledTor, passphrase, confirmedPassphrase, creatingWallet, torState ->
if(seedType == null || useProxy == null || proxyAddress == null || proxyPort == null || useBundledTor == null || passphrase == null || confirmedPassphrase == null || creatingWallet == null) return@combineLiveDatas 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@combineLiveDatas false if((passphrase.isNotEmpty() || confirmedPassphrase.isNotEmpty()) && passphrase != confirmedPassphrase) return@combineLiveDatas false
if(creatingWallet) return@combineLiveDatas false if(creatingWallet) return@combineLiveDatas false
if(seedType == SeedType.POLYSEED && (passphrase.isEmpty() || confirmedPassphrase.isEmpty())) return@combineLiveDatas false if(seedType == SeedType.POLYSEED && (passphrase.isEmpty() || confirmedPassphrase.isEmpty())) return@combineLiveDatas false
if(useProxy && (proxyAddress.isEmpty() || proxyPort.isEmpty())) return@combineLiveDatas false if(useProxy && (proxyAddress.isEmpty() || proxyPort.isEmpty()) && !useBundledTor) return@combineLiveDatas false
if(useBundledTor && (proxyAddress.isEmpty() || proxyPort.isEmpty())) return@combineLiveDatas false val progress = torState?.progressIndicator ?: 0
if(useBundledTor && progress < 100) return@combineLiveDatas false
return@combineLiveDatas true return@combineLiveDatas true
} }
@ -225,18 +227,16 @@ class OnboardingViewModel : ViewModel() {
fun setProxyAddress(address: String) { fun setProxyAddress(address: String) {
_proxyAddress.value = address _proxyAddress.value = address
if(address.isEmpty()) PrefService.instance?.deleteProxy()
val port = _proxyPort.value ?: return val port = _proxyPort.value ?: return
val proxyAddress = "$address:$port" ProxyService.instance?.updateProxy(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
if(port.isEmpty()) PrefService.instance?.deleteProxy()
val address = _proxyAddress.value ?: return val address = _proxyAddress.value ?: return
val proxyAddress = "$address:$port" ProxyService.instance?.updateProxy(address, port)
if(proxyAddress == ":") return
PrefService.instance?.edit()?.putString(Constants.PREF_PROXY, proxyAddress)?.apply()
} }
fun setUseBundledTor(useBundled: Boolean) { fun setUseBundledTor(useBundled: Boolean) {
@ -244,7 +244,7 @@ class OnboardingViewModel : ViewModel() {
PrefService.instance?.edit()?.putBoolean(Constants.PREF_USE_BUNDLED_TOR, useBundled)?.apply() PrefService.instance?.edit()?.putBoolean(Constants.PREF_USE_BUNDLED_TOR, useBundled)?.apply()
val samouraiTorManager = ProxyService.instance?.samouraiTorManager val samouraiTorManager = ProxyService.instance?.samouraiTorManager
if(useBundled && useProxy.value == true) { if(useBundled && ProxyService.instance?.usingProxy == true) {
samouraiTorManager?.start() samouraiTorManager?.start()
} else { } else {
samouraiTorManager?.stop() samouraiTorManager?.stop()
@ -256,7 +256,7 @@ class OnboardingViewModel : ViewModel() {
PrefService.instance?.edit()?.putBoolean(Constants.PREF_USES_PROXY, useProxy)?.apply() PrefService.instance?.edit()?.putBoolean(Constants.PREF_USES_PROXY, useProxy)?.apply()
val samouraiTorManager = ProxyService.instance?.samouraiTorManager val samouraiTorManager = ProxyService.instance?.samouraiTorManager
if(useProxy && useBundledTor.value == true) { if(useProxy && ProxyService.instance?.useBundledTor == true) {
samouraiTorManager?.start() samouraiTorManager?.start()
} else { } else {
samouraiTorManager?.stop() samouraiTorManager?.stop()

View file

@ -46,8 +46,6 @@ class SettingsFragment : Fragment(), PasswordListener, NodeSelectionDialogListen
private var walletProxyAddressEditText: EditText? = null private var walletProxyAddressEditText: EditText? = null
private var walletProxyPortEditText: EditText? = null private var walletProxyPortEditText: EditText? = null
private var selectNodeButton: Button? = null private var selectNodeButton: Button? = null
private var cachedProxyAddress: String = ""
private var cachedProxyPort: String = ""
private var streetModeSwitch: SwitchCompat? = null private var streetModeSwitch: SwitchCompat? = null
private var monerochanSwitch: SwitchCompat? = null private var monerochanSwitch: SwitchCompat? = null
private var donationSwitch: SwitchCompat? = null private var donationSwitch: SwitchCompat? = null
@ -87,8 +85,8 @@ class SettingsFragment : Fragment(), PasswordListener, NodeSelectionDialogListen
donationSwitch?.isChecked = PrefService.instance?.getBoolean(Constants.PREF_DONATE_PER_TX, false) == true donationSwitch?.isChecked = PrefService.instance?.getBoolean(Constants.PREF_DONATE_PER_TX, false) == true
val usesProxy = ProxyService.instance?.usingProxy == true val usesProxy = ProxyService.instance?.usingProxy == true
cachedProxyAddress = ProxyService.instance?.proxyAddress ?: return val cachedProxyAddress = ProxyService.instance?.proxyAddress ?: return
cachedProxyPort = ProxyService.instance?.proxyPort ?: return val cachedProxyPort = ProxyService.instance?.proxyPort ?: return
if (ProxyService.instance?.hasProxySet() == true) { if (ProxyService.instance?.hasProxySet() == true) {
initProxyStuff(cachedProxyAddress, cachedProxyPort) initProxyStuff(cachedProxyAddress, cachedProxyPort)
} }
@ -199,11 +197,7 @@ class SettingsFragment : Fragment(), PasswordListener, NodeSelectionDialogListen
torIcon?.visibility = View.INVISIBLE torIcon?.visibility = View.INVISIBLE
indicatorCircle?.visibility = View.INVISIBLE indicatorCircle?.visibility = View.INVISIBLE
} }
EnumTorState.STARTING -> { EnumTorState.STARTING, EnumTorState.STOPPING -> {
torIcon?.visibility = View.INVISIBLE
indicatorCircle?.visibility = View.VISIBLE
}
EnumTorState.STOPPING -> {
torIcon?.visibility = View.INVISIBLE torIcon?.visibility = View.INVISIBLE
indicatorCircle?.visibility = View.VISIBLE indicatorCircle?.visibility = View.VISIBLE
} }
@ -215,11 +209,7 @@ class SettingsFragment : Fragment(), PasswordListener, NodeSelectionDialogListen
private fun refreshProxy() { private fun refreshProxy() {
val proxyAddress = walletProxyAddressEditText?.text.toString() val proxyAddress = walletProxyAddressEditText?.text.toString()
val proxyPort = walletProxyPortEditText?.text.toString() val proxyPort = walletProxyPortEditText?.text.toString()
if((proxyAddress != cachedProxyAddress) || (proxyPort != cachedProxyPort)) {
ProxyService.instance?.updateProxy(proxyAddress, proxyPort) ProxyService.instance?.updateProxy(proxyAddress, proxyPort)
cachedProxyAddress = proxyAddress
cachedProxyPort = proxyPort
}
} }
private fun displaySeedDialog(password: String) { private fun displaySeedDialog(password: String) {

View file

@ -26,7 +26,7 @@ class SettingsViewModel : ViewModel() {
PrefService.instance?.edit()?.putBoolean(Constants.PREF_USES_PROXY, use)?.apply() PrefService.instance?.edit()?.putBoolean(Constants.PREF_USES_PROXY, use)?.apply()
val samouraiTorManager = ProxyService.instance?.samouraiTorManager val samouraiTorManager = ProxyService.instance?.samouraiTorManager
if(use && useBundledTor.value == true) { if(use && ProxyService.instance?.useBundledTor == true) {
samouraiTorManager?.start() samouraiTorManager?.start()
} else { } else {
samouraiTorManager?.stop() samouraiTorManager?.stop()
@ -34,11 +34,11 @@ class SettingsViewModel : ViewModel() {
} }
fun setUseBundledTor(use: Boolean) { fun setUseBundledTor(use: Boolean) {
PrefService.instance?.edit()?.putBoolean(Constants.PREF_USE_BUNDLED_TOR, use)?.apply()
_useBundledTor.value = use _useBundledTor.value = use
PrefService.instance?.edit()?.putBoolean(Constants.PREF_USE_BUNDLED_TOR, use)?.apply()
val samouraiTorManager = ProxyService.instance?.samouraiTorManager val samouraiTorManager = ProxyService.instance?.samouraiTorManager
if(use && useProxy.value == true) { if(use && ProxyService.instance?.usingProxy == true) {
samouraiTorManager?.start() samouraiTorManager?.start()
} else { } else {
samouraiTorManager?.stop() samouraiTorManager?.stop()

View file

@ -3,7 +3,7 @@ package net.mynero.wallet.livedata
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MediatorLiveData
fun <T1, T2, T3, T4, T5, T6, T7, T8, S> combineLiveDatas( fun <T1, T2, T3, T4, T5, T6, T7, T8, T9, S> combineLiveDatas(
source1: LiveData<T1>, source1: LiveData<T1>,
source2: LiveData<T2>, source2: LiveData<T2>,
source3: LiveData<T3>, source3: LiveData<T3>,
@ -12,7 +12,8 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, S> combineLiveDatas(
source6: LiveData<T6>, source6: LiveData<T6>,
source7: LiveData<T7>, source7: LiveData<T7>,
source8: LiveData<T8>, source8: LiveData<T8>,
func: (T1?, T2?, T3?, T4?, T5?, T6?, T7?, T8?) -> S? source9: LiveData<T9>?,
func: (T1?, T2?, T3?, T4?, T5?, T6?, T7?, T8?, T9?) -> S?
): LiveData<S> { ): LiveData<S> {
val result = MediatorLiveData<S>() val result = MediatorLiveData<S>()
result.addSource(source1) { result.addSource(source1) {
@ -24,7 +25,8 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, S> combineLiveDatas(
source5.value, source5.value,
source6.value, source6.value,
source7.value, source7.value,
source8.value source8.value,
source9?.value
)?.run { result.value = this } )?.run { result.value = this }
} }
@ -37,7 +39,8 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, S> combineLiveDatas(
source5.value, source5.value,
source6.value, source6.value,
source7.value, source7.value,
source8.value source8.value,
source9?.value
)?.run { result.value = this } )?.run { result.value = this }
} }
@ -50,7 +53,8 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, S> combineLiveDatas(
source5.value, source5.value,
source6.value, source6.value,
source7.value, source7.value,
source8.value source8.value,
source9?.value
)?.run { result.value = this } )?.run { result.value = this }
} }
@ -63,7 +67,8 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, S> combineLiveDatas(
source5.value, source5.value,
source6.value, source6.value,
source7.value, source7.value,
source8.value source8.value,
source9?.value
)?.run { result.value = this } )?.run { result.value = this }
} }
@ -76,7 +81,8 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, S> combineLiveDatas(
source5.value, source5.value,
source6.value, source6.value,
source7.value, source7.value,
source8.value source8.value,
source9?.value
)?.run { result.value = this } )?.run { result.value = this }
} }
@ -89,7 +95,8 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, S> combineLiveDatas(
source5.value, source5.value,
source6.value, source6.value,
source7.value, source7.value,
source8.value source8.value,
source9?.value
)?.run { result.value = this } )?.run { result.value = this }
} }
@ -102,7 +109,8 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, S> combineLiveDatas(
source5.value, source5.value,
source6.value, source6.value,
source7.value, source7.value,
source8.value source8.value,
source9?.value
)?.run { result.value = this } )?.run { result.value = this }
} }
@ -115,9 +123,27 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, S> combineLiveDatas(
source5.value, source5.value,
source6.value, source6.value,
source7.value, source7.value,
source8.value source8.value,
source9?.value
)?.run { result.value = this } )?.run { result.value = this }
} }
source9?.let { src9 ->
result.addSource(src9) {
func(
source1.value,
source2.value,
source3.value,
source4.value,
source5.value,
source6.value,
source7.value,
source8.value,
src9.value
)?.run { result.value = this }
}
}
return result return result
} }

View file

@ -15,6 +15,7 @@
*/ */
package net.mynero.wallet.model package net.mynero.wallet.model
import android.util.Log
import android.util.Pair import android.util.Pair
import net.mynero.wallet.data.Subaddress import net.mynero.wallet.data.Subaddress
import timber.log.Timber import timber.log.Timber
@ -60,7 +61,7 @@ class Wallet {
} }
fun setAccountIndex(accountIndex: Int) { fun setAccountIndex(accountIndex: Int) {
Timber.d("setAccountIndex(%d)", accountIndex) Log.d("Wallet.kt", "setAccountIndex($accountIndex)")
this.accountIndex = accountIndex this.accountIndex = accountIndex
history?.setAccountFor(this) history?.setAccountFor(this)
} }
@ -159,33 +160,33 @@ class Wallet {
var daemonUsername = WalletManager.instance?.daemonUsername var daemonUsername = WalletManager.instance?.daemonUsername
var daemonPassword = WalletManager.instance?.daemonPassword var daemonPassword = WalletManager.instance?.daemonPassword
var proxyAddress = WalletManager.instance?.proxy var proxyAddress = WalletManager.instance?.proxy
Timber.d("init(") Log.d("Wallet.kt", "init(")
if (daemonAddress != null) { if (daemonAddress != null) {
Timber.d(daemonAddress.toString()) Log.d("Wallet.kt", daemonAddress.toString())
} else { } else {
Timber.d("daemon_address == null") Log.d("Wallet.kt", "daemon_address == null")
daemonAddress = "" daemonAddress = ""
} }
Timber.d("upper_transaction_size_limit = 0 (probably)") Log.d("Wallet.kt", "upper_transaction_size_limit = 0 (probably)")
if (daemonUsername != null) { if (daemonUsername != null) {
Timber.d(daemonUsername) Log.d("Wallet.kt", daemonUsername)
} else { } else {
Timber.d("daemon_username == null") Log.d("Wallet.kt", "daemon_username == null")
daemonUsername = "" daemonUsername = ""
} }
if (daemonPassword != null) { if (daemonPassword != null) {
Timber.d(daemonPassword) Log.d("Wallet.kt", daemonPassword)
} else { } else {
Timber.d("daemon_password == null") Log.d("Wallet.kt", "daemon_password == null")
daemonPassword = "" daemonPassword = ""
} }
if (proxyAddress != null) { if (proxyAddress != null) {
Timber.d(proxyAddress) Log.d("Wallet.kt", proxyAddress)
} else { } else {
Timber.d("proxy_address == null") Log.d("Wallet.kt", "proxy_address == null")
proxyAddress = "" proxyAddress = ""
} }
Timber.d(");") Log.d("Wallet.kt", ");")
return initJ( return initJ(
daemonAddress, upperTransactionSizeLimit, daemonAddress, upperTransactionSizeLimit,
daemonUsername, daemonPassword, daemonUsername, daemonPassword,
@ -419,7 +420,7 @@ class Wallet {
val timeStamp = SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.US).format(Date()) val timeStamp = SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.US).format(Date())
addSubaddress(accountIndex, timeStamp) addSubaddress(accountIndex, timeStamp)
val subaddress = getLastSubaddress(accountIndex) val subaddress = getLastSubaddress(accountIndex)
Timber.d("%d: %s", getNumSubaddresses(accountIndex) - 1, subaddress) Log.d("Wallet.kt", "${(getNumSubaddresses(accountIndex) - 1)}: $subaddress")
return subaddress return subaddress
} }

View file

@ -2,6 +2,7 @@ package net.mynero.wallet.service
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.util.Log
import net.mynero.wallet.MoneroApplication import net.mynero.wallet.MoneroApplication
import net.mynero.wallet.data.DefaultNodes import net.mynero.wallet.data.DefaultNodes
import net.mynero.wallet.data.Node import net.mynero.wallet.data.Node
@ -79,6 +80,23 @@ class PrefService(application: MoneroApplication) : ServiceBase(null) {
return value == true return value == true
} }
fun saveProxy(address: String, port: String): String? {
if(address.isEmpty() || port.isEmpty()) {
deleteProxy()
return null
}
val proxyAddress = "$address:$port"
if(proxyAddress == ":") return null
Log.d("PrefService", "Setting proxy. proxyAddress=$proxyAddress")
edit()?.putString(Constants.PREF_PROXY, proxyAddress)?.apply()
return proxyAddress
}
fun deleteProxy() {
Log.d("PrefService", "Deleting proxy...")
edit()?.putString(Constants.PREF_PROXY, "")?.apply()
}
companion object { companion object {
private var preferences: SharedPreferences? = null private var preferences: SharedPreferences? = null

View file

@ -1,21 +1,20 @@
package net.mynero.wallet.service package net.mynero.wallet.service
import android.app.Application import android.app.Application
import android.util.Log
import android.util.Patterns import android.util.Patterns
import net.mynero.wallet.MainActivity
import net.mynero.wallet.livedata.SingleLiveEvent import net.mynero.wallet.livedata.SingleLiveEvent
import net.mynero.wallet.model.WalletManager import net.mynero.wallet.model.WalletManager
import net.mynero.wallet.util.Constants import net.mynero.wallet.util.Constants
class ProxyService(activity: MainActivity) : ServiceBase(null) { class ProxyService(application: Application) : ServiceBase(null) {
val proxyChangeEvents: SingleLiveEvent<String> = SingleLiveEvent() val proxyChangeEvents: SingleLiveEvent<String> = SingleLiveEvent()
var samouraiTorManager: SamouraiTorManager? = null var samouraiTorManager: SamouraiTorManager? = null
init { init {
samouraiTorManager = SamouraiTorManager(activity.application, TorKmpManager(activity.application))
instance = this instance = this
samouraiTorManager = SamouraiTorManager(application, TorKmpManager(application))
activity.runOnUiThread {
samouraiTorManager?.getTorStateLiveData()?.observeForever { samouraiTorManager?.getTorStateLiveData()?.observeForever {
samouraiTorManager?.getProxy()?.address()?.let { socketAddress -> samouraiTorManager?.getProxy()?.address()?.let { socketAddress ->
if(socketAddress.toString().isEmpty()) return@let if(socketAddress.toString().isEmpty()) return@let
@ -27,11 +26,10 @@ class ProxyService(activity: MainActivity) : ServiceBase(null) {
} }
} }
if(useBundledTor) { if(useBundledTor && usingProxy) {
samouraiTorManager?.start() samouraiTorManager?.start()
} }
} }
}
fun updateProxy(proxyAddress: String, proxyPort: String) { fun updateProxy(proxyAddress: String, proxyPort: String) {
var finalProxyAddress = proxyAddress var finalProxyAddress = proxyAddress
@ -43,16 +41,16 @@ class ProxyService(activity: MainActivity) : ServiceBase(null) {
if (!usingProxy || isNodeLocalIp) { if (!usingProxy || isNodeLocalIp) {
// User is not using proxy, or is using local node currently, so we will disable proxy here. // User is not using proxy, or is using local node currently, so we will disable proxy here.
proxyChangeEvents.postValue("") proxyChangeEvents.postValue("")
Log.d("ProxyService", "Not using proxy...")
return return
} }
// We are using proxy at this point, but user set them to empty. We will fallback to Tor defaults here. // We are using proxy at this point, but user set them to empty. We will fallback to Tor defaults here.
if (proxyAddress.isEmpty()) finalProxyAddress = "127.0.0.1" if (proxyAddress.isEmpty()) finalProxyAddress = "127.0.0.1"
if (proxyPort.isEmpty()) finalProxyPort = "9050" if (proxyPort.isEmpty()) finalProxyPort = "9050"
val validIpAddress = Patterns.IP_ADDRESS.matcher(proxyAddress).matches() val validIpAddress = Patterns.IP_ADDRESS.matcher(finalProxyAddress).matches()
if (validIpAddress) { if (validIpAddress) {
val proxy = "$finalProxyAddress:$finalProxyPort" val proxy = PrefService.instance?.saveProxy(finalProxyAddress, finalProxyPort)
PrefService.instance?.edit()?.putString(Constants.PREF_PROXY, proxy)?.apply() proxy?.let { proxyChangeEvents.postValue(it) }
proxyChangeEvents.postValue(proxy)
} }
} }

View file

@ -1,44 +1,41 @@
package net.mynero.wallet.service package net.mynero.wallet.service
import android.app.Application import android.app.Application
import android.util.Log
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import net.mynero.wallet.model.TorState import net.mynero.wallet.model.TorState
import org.json.JSONException
import org.json.JSONObject
import java.net.Proxy import java.net.Proxy
class SamouraiTorManager(val appContext: Application?, val torKmpManager: TorKmpManager?) { class SamouraiTorManager(private val appContext: Application?, private val torKmpManager: TorKmpManager) {
fun getTorStateLiveData(): MutableLiveData<TorState> { fun getTorStateLiveData(): MutableLiveData<TorState> {
return torKmpManager!!.torStateLiveData return torKmpManager.torStateLiveData
} }
fun getTorState(): TorState { fun getTorState(): TorState {
return torKmpManager!!.torState return torKmpManager.torState
} }
fun isConnected(): Boolean { fun isConnected(): Boolean {
return torKmpManager?.isConnected() ?: false return torKmpManager.isConnected()
} }
fun isStarting(): Boolean { fun isStarting(): Boolean {
return torKmpManager?.isStarting() ?: false return torKmpManager.isStarting()
} }
fun stop() { fun stop() {
torKmpManager?.torOperationManager?.stopQuietly() torKmpManager.torOperationManager.stopQuietly()
} }
fun start() { fun start() {
torKmpManager?.torOperationManager?.startQuietly() torKmpManager.torOperationManager.startQuietly()
} }
fun getProxy(): Proxy? { fun getProxy(): Proxy? {
return torKmpManager?.proxy return torKmpManager.proxy
} }
fun newIdentity() { fun newIdentity() {
torKmpManager?.newIdentity(appContext!!) appContext?.let { torKmpManager.newIdentity(it) }
} }
companion object { companion object {

View file

@ -16,7 +16,6 @@
android:text="@string/settings" android:text="@string/settings"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:layout_marginStart="24dp" android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:textSize="32sp" android:textSize="32sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@id/settings_tor_loading_progressindicator" app:layout_constraintEnd_toStartOf="@id/settings_tor_loading_progressindicator"
@ -28,10 +27,10 @@
android:layout_height="32dp" android:layout_height="32dp"
android:src="@drawable/tor" android:src="@drawable/tor"
android:visibility="invisible" android:visibility="invisible"
app:layout_constraintEnd_toEndOf="@id/settings_tor_loading_progressindicator" android:layout_marginEnd="24dp"
app:layout_constraintStart_toStartOf="@id/settings_tor_loading_progressindicator" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/settings_tor_loading_progressindicator" app:layout_constraintTop_toTopOf="@id/settings_textview"
app:layout_constraintBottom_toBottomOf="@id/settings_tor_loading_progressindicator"/> app:layout_constraintBottom_toBottomOf="@id/settings_textview"/>
<com.google.android.material.progressindicator.CircularProgressIndicator <com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/settings_tor_loading_progressindicator" android:id="@+id/settings_tor_loading_progressindicator"
@ -39,9 +38,10 @@
android:layout_height="32dp" android:layout_height="32dp"
android:indeterminate="true" android:indeterminate="true"
android:visibility="invisible" android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="@id/settings_tor_icon"
app:layout_constraintTop_toTopOf="@id/settings_textview" app:layout_constraintStart_toStartOf="@id/settings_tor_icon"
app:layout_constraintBottom_toBottomOf="@id/settings_textview"/> app:layout_constraintTop_toTopOf="@id/settings_tor_icon"
app:layout_constraintBottom_toBottomOf="@id/settings_tor_icon"/>
<TextView <TextView
android:id="@+id/wallet_settings_textview" android:id="@+id/wallet_settings_textview"