Skip to content

Commit

Permalink
fix(dashpay): update image permissions for Android 13 and fix camera (#…
Browse files Browse the repository at this point in the history
…1235)

* fix: update permissions for images on Android 13, refactor to use ActivityResultLauncher

* fix(dashpay): show the Join DashPay item on the home screen

* fix(dashpay): rename Username Voting Period Active
  • Loading branch information
HashEngineering authored Dec 20, 2023
1 parent e6b6144 commit 479ccd8
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 148 deletions.
3 changes: 2 additions & 1 deletion wallet/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

<!-- dangerous permissions -->
<uses-permission android:name="android.permission.CAMERA" /> <!-- group: CAMERA -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
Expand Down
2 changes: 1 addition & 1 deletion wallet/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ android {
compileSdk 33
minSdkVersion 23
targetSdkVersion 33
versionCode project.hasProperty('versionCode') ? project.property('versionCode') as int : 80133
versionCode project.hasProperty('versionCode') ? project.property('versionCode') as int : 90000
versionName project.hasProperty('versionName') ? project.property('versionName') : "5.3-dashpay"
multiDexEnabled true
generatedDensities = ['hdpi', 'xhdpi']
Expand Down
2 changes: 1 addition & 1 deletion wallet/res/layout/activity_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@

<TextView
style="@style/MenuRowTitle.Internal"
android:text="@string/voting_dash_pay"
android:text="@string/voting_period_active"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/voting_dash_pay_switch"
app:layout_constraintStart_toStartOf="parent"
Expand Down
2 changes: 1 addition & 1 deletion wallet/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@
<string name="quick_vote">Quick Voting</string>
<string name="quick_vote_subtitle">By tapping the "Vote for All" button, you will automatically vote for all of the filtered usernames (%d) that were submitted first</string>
<string name="vote_for_all">Vote for All</string>
<string name="voting_dash_pay">Voting Dash Pay</string>
<string name="voting_period_active">Username Voting Period Active</string>
<string name="there_was_a_network_error">There was a network error, you can try again at no extra cost</string>
<string name="requested_voting_duration">Requested · Voting: 1 Mar – 15 Mar</string>
<string name="cancel_request">Cancel Request</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,7 @@ void initViewModel() {
blockchainStateDao.load().observe(this, (blockchainState) -> handleBlockchainStateNotification(blockchainState, mixingStatus));
registerCrowdNodeConfirmedAddressFilter();

FlowExtKt.observe(coinJoinService.getMixingState(), this, (mixingStatus, continuation) -> {
FlowExtKt.observe(coinJoinService.observeMixingState(), this, (mixingStatus, continuation) -> {
handleBlockchainStateNotification(blockchainState, mixingStatus);
return null;
});
Expand Down
66 changes: 40 additions & 26 deletions wallet/src/de/schildbach/wallet/service/CoinJoinService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ import org.bitcoinj.coinjoin.PoolStatus
import org.bitcoinj.coinjoin.callbacks.RequestDecryptedKey
import org.bitcoinj.coinjoin.callbacks.RequestKeyParameter
import org.bitcoinj.coinjoin.listeners.CoinJoinTransactionListener
import org.bitcoinj.coinjoin.utils.CoinJoinTransactionType
import org.bitcoinj.coinjoin.listeners.MixingCompleteListener
import org.bitcoinj.coinjoin.listeners.SessionCompleteListener
import org.bitcoinj.coinjoin.progress.MixingProgressTracker
import org.bitcoinj.coinjoin.utils.CoinJoinManager
import org.bitcoinj.coinjoin.utils.CoinJoinTransactionType
import org.bitcoinj.core.AbstractBlockChain
import org.bitcoinj.core.Coin
import org.bitcoinj.core.Context
Expand Down Expand Up @@ -81,9 +81,9 @@ enum class CoinJoinMode {
* Monitor the status of the CoinJoin Mixing Service
*/
interface CoinJoinService {
val mixingStatus: MixingStatus
val mixingState: Flow<MixingStatus>
val mixingProgress: Flow<Double>
suspend fun getMixingState(): MixingStatus
fun observeMixingState(): Flow<MixingStatus>
fun observeMixingProgress(): Flow<Double>
}

enum class MixingStatus {
Expand Down Expand Up @@ -122,11 +122,11 @@ class CoinJoinMixingService @Inject constructor(
private var sessionCompleteListeners: ArrayList<SessionCompleteListener> = arrayListOf()

var mode: CoinJoinMode = CoinJoinMode.NONE
override var mixingStatus: MixingStatus = MixingStatus.NOT_STARTED
private set
val _mixingState = MutableStateFlow(MixingStatus.NOT_STARTED)
override val mixingState: Flow<MixingStatus>
get() = _mixingState
private val _mixingState = MutableStateFlow(MixingStatus.NOT_STARTED)
private val _progressFlow = MutableStateFlow(0.00)

override suspend fun getMixingState(): MixingStatus = _mixingState.value
override fun observeMixingState(): Flow<MixingStatus> = _mixingState

private val coroutineScope = CoroutineScope(
Executors.newFixedThreadPool(2, ContextPropagatingThreadFactory("coinjoin-pool")).asCoroutineDispatcher()
Expand All @@ -138,16 +138,15 @@ class CoinJoinMixingService @Inject constructor(
private val isBlockChainSet: Boolean
get() = blockChain != null
private var networkStatus: NetworkStatus = NetworkStatus.UNKNOWN
private var isSynced = false
private var hasAnonymizableBalance: Boolean = false

// https://stackoverflow.com/questions/55421710/how-to-suspend-kotlin-coroutine-until-notified
private val updateMutex = Mutex(locked = false)
private val updateMixingStateMutex = Mutex(locked = false)
private var exception: Throwable? = null

override val mixingProgress: Flow<Double>
get() = _progressFlow
private val _progressFlow = MutableStateFlow(0.00)
override fun observeMixingProgress(): Flow<Double> = _progressFlow

init {
blockchainStateProvider.observeNetworkStatus()
Expand All @@ -167,7 +166,12 @@ class CoinJoinMixingService @Inject constructor(
.filterNotNull()
.distinctUntilChanged()
.onEach { blockChainState ->
if (blockChainState.isSynced()) {
val isSynced = blockChainState.isSynced()
if (isSynced != this.isSynced) {
updateState(config.getMode(), hasAnonymizableBalance, networkStatus, isSynced, blockChain)
}
// this will trigger mixing as new blocks are mined and received tx's are confirmed
if (isSynced) {
log.info("coinjoin: new block: ${blockChainState.bestChainHeight}")
updateBalance(walletDataProvider.getWalletBalance())
}
Expand Down Expand Up @@ -204,32 +208,42 @@ class CoinJoinMixingService @Inject constructor(

val hasAnonymizableBalance = anonBalance.isGreaterThan(CoinJoin.getSmallestDenomination())
log.info("coinjoin: mixing can occur: $hasAnonymizableBalance")
updateState(config.getMode(), hasAnonymizableBalance, networkStatus, blockchainStateProvider.getBlockChain())
updateState(
config.getMode(),
hasAnonymizableBalance,
networkStatus,
isSynced,
blockchainStateProvider.getBlockChain()
)
}

private suspend fun updateState(
mode: CoinJoinMode,
hasAnonymizableBalance: Boolean,
networkStatus: NetworkStatus,
isSynced: Boolean,
blockChain: AbstractBlockChain?
) {
updateMutex.lock()
log.info("coinjoin-updateState: ${this.mode}, ${this.hasAnonymizableBalance}, ${this.networkStatus}, ${blockChain != null}")
log.info(
"coinjoin-updateState: ${this.mode}, ${this.hasAnonymizableBalance}, ${this.networkStatus}, ${this.isSynced} ${blockChain != null}"
)
try {
setBlockchain(blockChain)
log.info("coinjoin-updateState: $mode, $hasAnonymizableBalance, $networkStatus, ${blockChain != null}")
log.info(
"coinjoin-updateState: $mode, $hasAnonymizableBalance, $networkStatus, $isSynced, ${blockChain != null}"
)
this.networkStatus = networkStatus
this.mixingStatus = mixingStatus
_mixingState.value = mixingStatus
this.hasAnonymizableBalance = hasAnonymizableBalance
this.isSynced = isSynced
this.mode = mode

if (mode == CoinJoinMode.NONE) {
updateMixingState(MixingStatus.NOT_STARTED)
} else {
configureMixing()
if (hasAnonymizableBalance) {
if (networkStatus == NetworkStatus.CONNECTED && isBlockChainSet) {
if (networkStatus == NetworkStatus.CONNECTED && isBlockChainSet && isSynced) {
updateMixingState(MixingStatus.MIXING)
} else {
updateMixingState(MixingStatus.PAUSED)
Expand All @@ -250,9 +264,8 @@ class CoinJoinMixingService @Inject constructor(
) {
updateMixingStateMutex.lock()
try {

val previousMixingStatus = this.mixingStatus
this.mixingStatus = mixingStatus
val previousMixingStatus = _mixingState.value
_mixingState.value = mixingStatus
log.info("coinjoin-updateMixingState: $previousMixingStatus -> $mixingStatus")

when {
Expand All @@ -273,11 +286,11 @@ class CoinJoinMixingService @Inject constructor(
}

private suspend fun updateBlockChain(blockChain: AbstractBlockChain?) {
updateState(mode, hasAnonymizableBalance, networkStatus, blockChain)
updateState(mode, hasAnonymizableBalance, networkStatus, isSynced, blockChain)
}

private suspend fun updateNetworkStatus(networkStatus: NetworkStatus) {
updateState(mode, hasAnonymizableBalance, networkStatus, blockChain)
updateState(mode, hasAnonymizableBalance, networkStatus, isSynced, blockChain)
}

private suspend fun updateMode(mode: CoinJoinMode) {
Expand All @@ -286,7 +299,7 @@ class CoinJoinMixingService @Inject constructor(
configureMixing()
updateBalance(walletDataProvider.wallet!!.getBalance(Wallet.BalanceType.AVAILABLE))
}
updateState(mode, hasAnonymizableBalance, networkStatus, blockChain)
updateState(mode, hasAnonymizableBalance, networkStatus, isSynced, blockChain)
}

private var mixingProgressTracker: MixingProgressTracker = object : MixingProgressTracker() {
Expand Down Expand Up @@ -347,6 +360,7 @@ class CoinJoinMixingService @Inject constructor(
private fun configureMixing() {
configureMixing(walletDataProvider.getWalletBalance())
}

/** set CoinJoinClientOptions based on CoinJoinMode */
private fun configureMixing(amount: Coin) {
when (mode) {
Expand Down Expand Up @@ -389,7 +403,7 @@ class CoinJoinMixingService @Inject constructor(
clientManager = CoinJoinClientManager(wallet)
coinJoinClientManagers[wallet.description] = clientManager
// this allows mixing to wait for the last transaction to be confirmed
//clientManager.addContinueMixingOnError(PoolStatus.ERR_NO_INPUTS)
// clientManager.addContinueMixingOnError(PoolStatus.ERR_NO_INPUTS)
// wait until the masternode sync system fixes itself
clientManager.addContinueMixingOnError(PoolStatus.ERR_NO_MASTERNODES_DETECTED)
clientManager.setStopOnNothingToDo(true)
Expand Down
Loading

0 comments on commit 479ccd8

Please sign in to comment.