Skip to content

Commit 0d51222

Browse files
authored
Merge pull request #416 from code-payments/feat/not-activate-tip-card-flow
feat: add prompt flow when scanning non-activated tip cards
2 parents 310ae96 + 30b9e00 commit 0d51222

File tree

8 files changed

+94
-50
lines changed

8 files changed

+94
-50
lines changed

api/src/main/java/com/getcode/network/TipController.kt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ import com.getcode.network.client.Client
1313
import com.getcode.network.client.fetchTwitterUser
1414
import com.getcode.network.repository.PrefRepository
1515
import com.getcode.network.repository.TwitterUserFetchError
16+
import com.getcode.network.repository.base58
17+
import com.getcode.utils.bytes
1618
import com.getcode.utils.getOrPutIfNonNull
19+
import com.getcode.vendor.Base58
1720
import kotlinx.coroutines.CoroutineScope
1821
import kotlinx.coroutines.Dispatchers
1922
import kotlinx.coroutines.flow.Flow
@@ -31,6 +34,7 @@ import kotlinx.serialization.encodeToString
3134
import kotlinx.serialization.json.Json
3235
import timber.log.Timber
3336
import java.util.Timer
37+
import java.util.UUID
3438
import javax.inject.Inject
3539
import javax.inject.Singleton
3640
import kotlin.concurrent.fixedRateTimer
@@ -142,6 +146,27 @@ class TipController @Inject constructor(
142146
prefRepository.set(PrefsBool.SEEN_TIP_CARD, true)
143147
}
144148

149+
fun generateTipVerification(): String? {
150+
val authority = SessionManager.getOrganizer()?.tray?.owner?.getCluster()?.authority
151+
val tipAddress = SessionManager.getOrganizer()?.primaryVault
152+
?.let { Base58.encode(it.byteArray) }
153+
154+
if (tipAddress != null && authority != null) {
155+
val nonce = UUID.randomUUID()
156+
val signature = authority.keyPair.sign(nonce.bytes.toByteArray())
157+
val verificationMessage = listOf(
158+
"CodeAccount",
159+
tipAddress,
160+
Base58.encode(nonce.bytes.toByteArray()),
161+
signature.base58
162+
).joinToString(":")
163+
164+
return verificationMessage
165+
}
166+
167+
return null
168+
}
169+
145170
private fun stopTimer() {
146171
pollTimer?.cancel()
147172
}
Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,14 @@
11
package com.getcode.util
22

33
import android.content.Context
4-
import android.content.Intent
5-
import android.net.Uri
6-
import android.provider.Settings
74
import androidx.core.content.ContextCompat
8-
import com.getcode.BuildConfig
9-
import com.getcode.utils.makeE164
105

116
fun Context.launchAppSettings() {
12-
ContextCompat.startActivity(
13-
this,
14-
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
15-
data = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null)
16-
flags = Intent.FLAG_ACTIVITY_NEW_TASK
17-
},
18-
null
19-
)
7+
val intent = IntentUtils.appSettings()
8+
ContextCompat.startActivity(this, intent, null)
209
}
2110

2211
fun Context.launchSmsIntent(phoneValue: String, message: String) {
23-
val uri: Uri = Uri.parse("smsto:${phoneValue.makeE164()}")
24-
val intent = Intent(Intent.ACTION_SENDTO, uri)
25-
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
26-
intent.putExtra(
27-
"sms_body",
28-
message
29-
)
12+
val intent = IntentUtils.sendSms(phoneValue, message)
3013
ContextCompat.startActivity(this, intent, null)
3114
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.getcode.util
2+
3+
import android.content.Intent
4+
import android.net.Uri
5+
import android.provider.Settings
6+
import com.getcode.BuildConfig
7+
import com.getcode.network.repository.urlEncode
8+
import com.getcode.utils.makeE164
9+
10+
object IntentUtils {
11+
12+
fun appSettings() = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
13+
data = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null)
14+
flags = Intent.FLAG_ACTIVITY_NEW_TASK
15+
}
16+
17+
fun sendSms(phoneValue: String, message: String) = Intent(
18+
Intent.ACTION_SENDTO,
19+
Uri.parse("smsto:${phoneValue.makeE164()}")
20+
).apply {
21+
flags = Intent.FLAG_ACTIVITY_NEW_TASK
22+
putExtra("sms_body", message)
23+
}
24+
25+
fun tweet(message: String) = Intent(Intent.ACTION_VIEW).apply {
26+
val url = "https://www.twitter.com/intent/tweet?text=${message.urlEncode()}"
27+
setData(Uri.parse(url))
28+
flags = Intent.FLAG_ACTIVITY_NEW_TASK
29+
}
30+
}

app/src/main/java/com/getcode/view/main/home/HomeViewModel.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import com.getcode.network.repository.toPublicKey
7373
import com.getcode.solana.organizer.GiftCardAccount
7474
import com.getcode.solana.organizer.Organizer
7575
import com.getcode.util.CurrencyUtils
76+
import com.getcode.util.IntentUtils
7677
import com.getcode.util.Kin
7778
import com.getcode.util.formatted
7879
import com.getcode.util.resources.ResourceHelper
@@ -727,8 +728,22 @@ class HomeViewModel @Inject constructor(
727728
scannedRendezvous.add(payload.rendezvous.publicKey)
728729
cancelTip()
729730
TopBarManager.showMessage(
730-
resources.getString(R.string.error_title_invalidTipCard),
731-
resources.getString(R.string.error_description_invalidTipCard),
731+
TopBarManager.TopBarMessage(
732+
title = resources.getString(R.string.error_title_invalidTipCard),
733+
message = resources.getString(R.string.error_description_invalidTipCard),
734+
primaryText = resources.getString(R.string.action_tweetThem),
735+
primaryAction = {
736+
val intent = IntentUtils.tweet(
737+
resources.getString(
738+
R.string.subtitle_linkingTwitterPrompt, username
739+
)
740+
)
741+
viewModelScope.launch {
742+
_eventFlow.emit(HomeEvent.SendIntent(intent))
743+
}
744+
},
745+
secondaryText = resources.getString(R.string.action_notNow)
746+
)
732747
)
733748
}.onSuccess {
734749
delay(300.milliseconds)

app/src/main/java/com/getcode/view/main/tip/TipConnectViewModel.kt

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,22 @@ import android.content.Intent
44
import android.net.Uri
55
import androidx.lifecycle.viewModelScope
66
import com.getcode.R
7-
import com.getcode.manager.SessionManager
8-
import com.getcode.network.repository.base58
7+
import com.getcode.network.TipController
98
import com.getcode.network.repository.urlEncode
9+
import com.getcode.util.IntentUtils
1010
import com.getcode.util.resources.ResourceHelper
11-
import com.getcode.utils.bytes
12-
import com.getcode.vendor.Base58
1311
import com.getcode.view.BaseViewModel2
1412
import dagger.hilt.android.lifecycle.HiltViewModel
1513
import kotlinx.coroutines.flow.filterIsInstance
1614
import kotlinx.coroutines.flow.launchIn
1715
import kotlinx.coroutines.flow.map
1816
import kotlinx.coroutines.flow.onEach
19-
import java.util.UUID
2017
import javax.inject.Inject
2118

2219
@HiltViewModel
2320
class TipConnectViewModel @Inject constructor(
2421
resources: ResourceHelper,
22+
tipController: TipController,
2523
) : BaseViewModel2<TipConnectViewModel.State, TipConnectViewModel.Event>(
2624
initialState = State(""),
2725
updateStateForEvent = updateStateForEvent
@@ -38,20 +36,8 @@ class TipConnectViewModel @Inject constructor(
3836
}
3937

4038
init {
41-
val authority = SessionManager.getOrganizer()?.tray?.owner?.getCluster()?.authority
42-
val tipAddress = SessionManager.getOrganizer()?.primaryVault
43-
?.let { Base58.encode(it.byteArray) }
44-
45-
if (tipAddress != null && authority != null) {
46-
val nonce = UUID.randomUUID()
47-
val signature = authority.keyPair.sign(nonce.bytes.toByteArray())
48-
val verificationMessage = listOf(
49-
"CodeAccount",
50-
tipAddress,
51-
Base58.encode(nonce.bytes.toByteArray()),
52-
signature.base58
53-
).joinToString(":")
54-
39+
val verificationMessage = tipController.generateTipVerification()
40+
if (verificationMessage != null) {
5541
val message = """
5642
${resources.getString(R.string.subtitle_linkingTwitter)}
5743
@@ -62,11 +48,9 @@ class TipConnectViewModel @Inject constructor(
6248

6349
eventFlow
6450
.filterIsInstance<Event.PostToX>()
65-
.map {
66-
// build intent
67-
val url = "https://www.twitter.com/intent/tweet?text=${stateFlow.value.xMessage.urlEncode()}"
68-
Intent(Intent.ACTION_VIEW).apply { setData(Uri.parse(url)) }
69-
}.onEach {
51+
.map { stateFlow.value.xMessage }
52+
.map { IntentUtils.tweet(it) }
53+
.onEach {
7054
dispatchEvent(Event.OpenX(it))
7155
}.launchIn(viewModelScope)
7256
}

app/src/main/res/values-en-rGB/strings-localized.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@
262262
<string name="subtitle_smsWasSent">An SMS message was sent to your phone number with a verification code. Please enter the verification code above.</string>
263263
<string name="subtitle_someoneSendYouCash">Someone sent you cash</string>
264264
<string name="subtitle_someoneTippedYou">Someone tipped you</string>
265-
<string name="subtitle_tipCardForX">Your Tip Card lets you receive tips from Code users all over the world. To access your Tip Card connect your X identity.</string>
265+
<string name="subtitle_tipCardForX">Your Tip Card lets you receive tips from Code users all over the world. To access your Tip Card post to X.</string>
266266
<string name="subtitle_typeDelete">Type \"%1$s\"</string>
267267
<string name="subtitle_updateRequiredDescription">We\'ve made some changes to improve the experience. You\'ll need to update the app to keep using Code.</string>
268268
<string name="subtitle_validOwnerAccount">Valid owner account</string>

app/src/main/res/values/strings-localized.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494
<string name="error_description_insuffiecientKin">To learn how to get more Kin go to the FAQ in Settings.</string>
9595
<string name="error_description_invalidInviteCode">Please enter a different Invite Code and try again.</string>
9696
<string name="error_description_invalidInvitePhone">Please enter a valid phone number and try again.</string>
97-
<string name="error_description_invalidTipCard">This is an invalid Tip Card.</string>
97+
<string name="error_description_invalidTipCard">Send a tweet to this person to activate their Tip Card.</string>
9898
<string name="error_description_invalidVerificationCode">Please enter a valid code and try again.</string>
9999
<string name="error_description_invitationFailed">Sorry, we experienced a network issue. Please try inviting your friend again.</string>
100100
<string name="error_description_linkExpired">This Kin was automatically returned to the sender because it wasn\'t collected within 24 hours. Please ask them to send the Kin again.</string>
@@ -124,7 +124,7 @@
124124
<string name="error_title_insuffiecientKin">Insufficient Kin</string>
125125
<string name="error_title_invalidInviteCode">Invite Code Invalid or Expired</string>
126126
<string name="error_title_invalidInvitePhone">Invalid Phone Number</string>
127-
<string name="error_title_invalidTipCard">Invalid Tip Card</string>
127+
<string name="error_title_invalidTipCard">Tip Card Not Yet Activated.</string>
128128
<string name="error_title_invalidVerificationCode">Invalid Code</string>
129129
<string name="error_title_invitationFailed">Invitation Failed</string>
130130
<string name="error_title_linkExpired">Link Expired</string>
@@ -262,7 +262,7 @@
262262
<string name="subtitle_smsWasSent">An SMS message was sent to your phone number with a verification code. Please enter the verification code above.</string>
263263
<string name="subtitle_someoneSendYouCash">Someone sent you cash</string>
264264
<string name="subtitle_someoneTippedYou">Someone tipped you</string>
265-
<string name="subtitle_tipCardForX">Your Tip Card lets you to receive tips from Code users all over the world. To access your Tip Card connect your X identity.</string>
265+
<string name="subtitle_tipCardForX">Your Tip Card lets you to receive tips from Code users all over the world. To access your Tip Card post to X.</string>
266266
<string name="subtitle_typeDelete">Type \"%1$s\"</string>
267267
<string name="subtitle_updateRequiredDescription">We\'ve made some changes to improve the experience. You\'ll need to update the app to keep using Code.</string>
268268
<string name="subtitle_validOwnerAccount">Valid owner account</string>

app/src/main/res/values/strings.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,11 @@
3333
<string name="title_chat_announcement_thanksReceived">🙏 %1$s thanked you for your tip</string>
3434

3535
<string name="title_sendKin">Send Kin</string>
36+
<string name="action_tweetThem">Tweet Them</string>
37+
<string name="subtitle_linkingTwitterPrompt">
38+
Hey @%1$s you should set up your @getcode Tip Card so I can tip you some cash.
39+
40+
getcode.com/download
41+
</string>
42+
3643
</resources>

0 commit comments

Comments
 (0)