Skip to content

Commit 656106a

Browse files
committed
chore: add connect account flow for identity reveal
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 830887f commit 656106a

9 files changed

Lines changed: 93 additions & 33 deletions

File tree

app/src/main/java/com/getcode/navigation/screens/ModalScreens.kt

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ import com.getcode.view.main.getKin.BuyKinScreen
3030
import com.getcode.view.main.getKin.GetKinSheet
3131
import com.getcode.view.main.getKin.GetKinSheetViewModel
3232
import com.getcode.view.main.tip.EnterTipScreen
33-
import com.getcode.view.main.tip.RequestTipScreen
33+
import com.getcode.view.main.tip.IdentityConnectionReason
34+
import com.getcode.view.main.tip.ConnectAccountScreen
35+
import com.getcode.view.main.tip.TipConnectViewModel
3436
import kotlinx.parcelize.IgnoredOnParcel
3537
import kotlinx.parcelize.Parcelize
3638

@@ -393,23 +395,32 @@ data class EnterTipModal(val isInChat: Boolean = false) : MainGraph, ModalRoot {
393395
}
394396

395397
@Parcelize
396-
data object RequestTip : MainGraph, ModalContent {
398+
data class ConnectAccount(
399+
private val reason: IdentityConnectionReason = IdentityConnectionReason.TipCard,
400+
) : MainGraph, ModalContent {
397401
@IgnoredOnParcel
398402
override val key: ScreenKey = uniqueScreenKey
399403

400404
@Composable
401405
override fun Content() {
402406
val navigator = LocalCodeNavigator.current
407+
val viewModel = getViewModel<TipConnectViewModel>()
403408
ModalContainer(
404409
backButtonEnabled = {
405410
if (navigator.isVisible) {
406-
it is RequestTip
411+
it is ConnectAccount
407412
} else {
408413
navigator.progress > 0f
409414
}
410415
}
411416
) {
412-
RequestTipScreen(getViewModel())
417+
418+
ConnectAccountScreen(viewModel)
419+
}
420+
421+
422+
LaunchedEffect(viewModel, reason) {
423+
viewModel.dispatchEvent(TipConnectViewModel.Event.OnReasonChanged(reason))
413424
}
414425
}
415426
}

app/src/main/java/com/getcode/view/main/chat/conversation/ChatConversationScreen.kt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ package com.getcode.view.main.chat.conversation
44

55
import androidx.compose.animation.AnimatedContent
66
import androidx.compose.foundation.ExperimentalFoundationApi
7-
import androidx.compose.foundation.layout.Arrangement
87
import androidx.compose.foundation.layout.Column
98
import androidx.compose.foundation.layout.fillMaxSize
109
import androidx.compose.foundation.layout.fillMaxWidth
@@ -24,20 +23,18 @@ import androidx.compose.ui.Alignment
2423
import androidx.compose.ui.Modifier
2524
import androidx.compose.ui.graphics.Color
2625
import androidx.compose.ui.text.AnnotatedString
27-
import androidx.compose.ui.text.SpanStyle
28-
import androidx.compose.ui.text.buildAnnotatedString
2926
import androidx.compose.ui.text.font.FontWeight
30-
import androidx.compose.ui.text.style.TextDecoration
31-
import androidx.compose.ui.text.withStyle
3227
import androidx.paging.compose.LazyPagingItems
33-
import com.getcode.manager.BottomBarManager
28+
import com.getcode.navigation.core.LocalCodeNavigator
29+
import com.getcode.navigation.screens.ConnectAccount
3430
import com.getcode.theme.CodeTheme
3531
import com.getcode.ui.components.CodeScaffold
3632
import com.getcode.ui.components.chat.utils.ChatItem
3733
import com.getcode.ui.components.chat.ChatInput
3834
import com.getcode.ui.components.chat.MessageList
3935
import com.getcode.ui.components.chat.MessageListEvent
4036
import com.getcode.ui.components.chat.utils.HandleMessageChanges
37+
import com.getcode.view.main.tip.IdentityConnectionReason
4138
import kotlinx.coroutines.delay
4239

4340
@Composable
@@ -46,13 +43,14 @@ fun ChatConversationScreen(
4643
messages: LazyPagingItems<ChatItem>,
4744
dispatchEvent: (ConversationViewModel.Event) -> Unit,
4845
) {
46+
val navigator = LocalCodeNavigator.current
4947
CodeScaffold(
5048
topBar = {
5149
IdentityRevealHeader(state = state) {
5250
if (state.identityAvailable) {
5351
dispatchEvent(ConversationViewModel.Event.RevealIdentity)
5452
} else {
55-
// TODO: connect UI flow
53+
navigator.push(ConnectAccount(IdentityConnectionReason.IdentityReveal))
5654
}
5755
}
5856
},

app/src/main/java/com/getcode/view/main/chat/conversation/ConversationViewModel.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import androidx.paging.map
1212
import com.getcode.BuildConfig
1313
import com.getcode.R
1414
import com.getcode.manager.BottomBarManager
15+
import com.getcode.manager.TopBarManager
1516
import com.getcode.model.ConversationWithLastPointers
1617
import com.getcode.model.Feature
1718
import com.getcode.model.ID
@@ -34,6 +35,7 @@ import com.getcode.utils.timestamp
3435
import com.getcode.view.BaseViewModel2
3536
import dagger.hilt.android.lifecycle.HiltViewModel
3637
import kotlinx.coroutines.Dispatchers
38+
import kotlinx.coroutines.delay
3739
import kotlinx.coroutines.flow.Flow
3840
import kotlinx.coroutines.flow.distinctUntilChanged
3941
import kotlinx.coroutines.flow.filter

app/src/main/java/com/getcode/view/main/getKin/GetKinSheet.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import com.getcode.navigation.screens.BuyMoreKinModal
4343
import com.getcode.navigation.screens.BuySellScreen
4444
import com.getcode.navigation.screens.HomeResult
4545
import com.getcode.navigation.screens.RequestKinModal
46-
import com.getcode.navigation.screens.RequestTip
46+
import com.getcode.navigation.screens.ConnectAccount
4747
import com.getcode.theme.BrandLight
4848
import com.getcode.theme.BrandMuted
4949
import com.getcode.theme.CodeTheme
@@ -114,7 +114,7 @@ fun GetKinSheet(
114114
if (dataState.isTipCardConnected) {
115115
navigator.hideWithResult(HomeResult.ShowTipCard)
116116
} else {
117-
navigator.push(RequestTip)
117+
navigator.push(ConnectAccount())
118118
}
119119
},
120120
),

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ private fun HomeScan(
161161
mutableStateOf(dataState.autoStartCamera == true)
162162
}
163163

164+
LaunchedEffect(previewing) {
165+
homeViewModel.onCameraScanning(previewing)
166+
}
167+
164168
val focusManager = LocalFocusManager.current
165169

166170
var deepLinkSaved by remember(deepLink) {

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ class HomeViewModel @Inject constructor(
238238
.flatMapLatest { tipController.connectedAccount }
239239
.filterNotNull()
240240
.distinctUntilChanged()
241+
.filter { uiFlow.value.isCameraScanEnabled }
241242
.onEach {
242243
when (it) {
243244
is TwitterUser -> {
@@ -375,6 +376,10 @@ class HomeViewModel @Inject constructor(
375376
}
376377
}
377378

379+
fun onCameraScanning(scanning: Boolean) {
380+
uiFlow.update { it.copy(isCameraScanEnabled = scanning) }
381+
}
382+
378383
fun onCameraPermissionChanged(isGranted: Boolean) {
379384
uiFlow.update { it.copy(isCameraPermissionGranted = isGranted) }
380385
}

app/src/main/java/com/getcode/view/main/tip/RequestTipScreen.kt renamed to app/src/main/java/com/getcode/view/main/tip/ConnectAccountScreen.kt

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,13 @@ import kotlinx.coroutines.flow.filterIsInstance
4545
import kotlinx.coroutines.flow.launchIn
4646
import kotlinx.coroutines.flow.onEach
4747

48+
enum class IdentityConnectionReason {
49+
TipCard,
50+
IdentityReveal,
51+
}
52+
4853
@Composable
49-
fun RequestTipScreen(
54+
fun ConnectAccountScreen(
5055
viewModel: TipConnectViewModel = hiltViewModel()
5156
) {
5257
val state by viewModel.stateFlow.collectAsState()
@@ -59,7 +64,10 @@ fun RequestTipScreen(
5964
.onEach {
6065
composeTweet(context, it.intent)
6166
delay(1_000)
62-
navigator.hide()
67+
when (state.reason) {
68+
IdentityConnectionReason.IdentityReveal -> navigator.pop()
69+
else -> navigator.hide()
70+
}
6371
}
6472
.launchIn(this)
6573
}
@@ -78,11 +86,19 @@ fun RequestTipScreen(
7886
@Composable
7987
private fun ColumnScope.RequestContent(state: TipConnectViewModel.State, onClick: () -> Unit) {
8088
Text(
81-
text = stringResource(id = R.string.title_requestTip),
89+
text = when(state.reason) {
90+
IdentityConnectionReason.TipCard -> stringResource(id = R.string.title_requestTip)
91+
IdentityConnectionReason.IdentityReveal -> stringResource(id = R.string.title_connectAccount)
92+
null -> ""
93+
},
8294
style = CodeTheme.typography.displayMedium.bolded()
8395
)
8496
Text(
85-
text = stringResource(id = R.string.subtitle_tipCardForX),
97+
text = when(state.reason) {
98+
IdentityConnectionReason.TipCard -> stringResource(id = R.string.subtitle_tipCardForX)
99+
IdentityConnectionReason.IdentityReveal -> stringResource(id = R.string.subtitle_connectXAccount)
100+
null -> ""
101+
},
86102
style = CodeTheme.typography.textSmall
87103
)
88104
Spacer(modifier = Modifier.weight(0.3f))
@@ -142,6 +158,8 @@ private fun composeTweet(context: Context, intent: Intent) {
142158
@Composable
143159
private fun Preview_TweetPreview() {
144160
CodeTheme {
145-
TweetPreview(xMessage = "I’m connecting my X account with @getcode so I can receive tips from people all over the world. My accountForX=fh5g376")
161+
TweetPreview(xMessage = "I’m connecting my X account with @getcode\n" +
162+
"\n" +
163+
"CodeAccount:349pQtzGmiBxU9vADVf6AUdMLLXyCCU3Zu4smrQPXved:zGmiBxU9vADVf6AUdMLLXyCCU3Zu4smrQP")
146164
}
147165
}

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

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
package com.getcode.view.main.tip
22

33
import android.content.Intent
4-
import android.net.Uri
54
import androidx.lifecycle.viewModelScope
65
import com.getcode.R
76
import com.getcode.network.TipController
8-
import com.getcode.network.repository.urlEncode
97
import com.getcode.util.IntentUtils
108
import com.getcode.util.resources.ResourceHelper
119
import com.getcode.view.BaseViewModel2
1210
import dagger.hilt.android.lifecycle.HiltViewModel
1311
import kotlinx.coroutines.flow.filterIsInstance
1412
import kotlinx.coroutines.flow.launchIn
1513
import kotlinx.coroutines.flow.map
14+
import kotlinx.coroutines.flow.mapNotNull
1615
import kotlinx.coroutines.flow.onEach
1716
import javax.inject.Inject
1817

@@ -21,30 +20,48 @@ class TipConnectViewModel @Inject constructor(
2120
resources: ResourceHelper,
2221
tipController: TipController,
2322
) : BaseViewModel2<TipConnectViewModel.State, TipConnectViewModel.Event>(
24-
initialState = State(""),
23+
initialState = State(null, ""),
2524
updateStateForEvent = updateStateForEvent
2625
) {
2726

2827
data class State(
28+
val reason: IdentityConnectionReason?,
2929
val xMessage: String,
3030
)
3131

3232
sealed interface Event {
33-
data class UpdateMessage(val message: String): Event
34-
data object PostToX: Event
35-
data class OpenX(val intent: Intent): Event
33+
data class OnReasonChanged(val reason: IdentityConnectionReason) : Event
34+
data class UpdateMessage(val message: String) : Event
35+
data object PostToX : Event
36+
data class OpenX(val intent: Intent) : Event
3637
}
3738

3839
init {
39-
val verificationMessage = tipController.generateTipVerification()
40-
if (verificationMessage != null) {
41-
val message = """
42-
${resources.getString(R.string.subtitle_linkingTwitter)}
43-
44-
$verificationMessage
45-
""".trimIndent()
46-
dispatchEvent(Event.UpdateMessage(message))
47-
}
40+
eventFlow
41+
.filterIsInstance<Event.OnReasonChanged>()
42+
.map { it.reason }
43+
.mapNotNull {
44+
val verificationMessage = tipController.generateTipVerification() ?: return@mapNotNull null
45+
when (it) {
46+
IdentityConnectionReason.TipCard -> {
47+
"""
48+
${resources.getString(R.string.subtitle_linkingTwitter)}
49+
50+
$verificationMessage
51+
""".trimIndent()
52+
}
53+
54+
IdentityConnectionReason.IdentityReveal -> {
55+
"""
56+
${resources.getString(R.string.subtitle_linkingTwitterToRevealIdentity)}
57+
58+
$verificationMessage
59+
""".trimIndent()
60+
}
61+
}
62+
}.onEach {
63+
dispatchEvent(Event.UpdateMessage(it))
64+
}.launchIn(viewModelScope)
4865

4966
eventFlow
5067
.filterIsInstance<Event.PostToX>()
@@ -58,6 +75,7 @@ class TipConnectViewModel @Inject constructor(
5875
companion object {
5976
val updateStateForEvent: (Event) -> ((State) -> State) = { event ->
6077
when (event) {
78+
is Event.OnReasonChanged -> { state -> state.copy(reason = event.reason) }
6179
is Event.UpdateMessage -> { state -> state.copy(xMessage = event.message) }
6280
is Event.OpenX -> { state -> state }
6381
Event.PostToX -> { state -> state }

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,8 @@
4545
<string name="title_accessKeySnapshotDescription">Warning! This image gives access to all the funds you have in Code. Do not share this image with anyone else.\nKeep it secure and safe.</string>
4646
<string name="prompt_title_revealIdentity">Reveal your identity?</string>
4747
<string name="prompt_subtitle_revealIdentity">%1$s will be able to see that you are %2$s.</string>
48+
49+
<string name="subtitle_linkingTwitterToRevealIdentity">I\'m connecting my X account with @getcode</string>
50+
<string name="title_connectAccount">Connect Account</string>
51+
<string name="subtitle_connectXAccount">Connecting your X account allows you to reveal your identity to the people you tip. To connect your account post to X.</string>
4852
</resources>

0 commit comments

Comments
 (0)