@@ -52,6 +52,9 @@ import com.duckduckgo.sync.impl.ui.SyncWithAnotherActivityViewModel.Command.Read
52
52
import com.duckduckgo.sync.impl.ui.SyncWithAnotherActivityViewModel.Command.ShowError
53
53
import com.duckduckgo.sync.impl.ui.SyncWithAnotherActivityViewModel.Command.ShowMessage
54
54
import com.duckduckgo.sync.impl.ui.SyncWithAnotherActivityViewModel.Command.SwitchAccountSuccess
55
+ import com.duckduckgo.sync.impl.ui.qrcode.SyncBarcodeDecorator
56
+ import com.duckduckgo.sync.impl.ui.qrcode.SyncBarcodeDecorator.CodeType.Exchange
57
+ import com.duckduckgo.sync.impl.ui.qrcode.SyncBarcodeDecorator.CodeType.Recovery
55
58
import com.duckduckgo.sync.impl.ui.setup.EnterCodeContract.EnterCodeContractOutput
56
59
import javax.inject.Inject
57
60
import kotlinx.coroutines.channels.BufferOverflow.DROP_OLDEST
@@ -73,11 +76,12 @@ class SyncWithAnotherActivityViewModel @Inject constructor(
73
76
private val syncPixels : SyncPixels ,
74
77
private val dispatchers : DispatcherProvider ,
75
78
private val syncFeature : SyncFeature ,
79
+ private val urlDecorator : SyncBarcodeDecorator ,
76
80
) : ViewModel() {
77
81
private val command = Channel <Command >(1 , DROP_OLDEST )
78
82
fun commands (): Flow <Command > = command.receiveAsFlow()
79
83
80
- private var barcodeContents: String ? = null
84
+ private var barcodeContents: BarcodeContents ? = null
81
85
82
86
private val viewState = MutableStateFlow (ViewState ())
83
87
fun viewState (): Flow <ViewState > = viewState.onStart {
@@ -108,17 +112,23 @@ class SyncWithAnotherActivityViewModel @Inject constructor(
108
112
}
109
113
110
114
private suspend fun showQRCode () {
111
- val shouldExchangeKeysToSyncAnotherDevice = syncFeature.exchangeKeysToSyncWithAnotherDevice().isEnabled()
112
-
113
- if (! shouldExchangeKeysToSyncAnotherDevice) {
114
- syncAccountRepository.getRecoveryCode()
115
+ // get the code as a Result, and pair it with the type of code we're dealing with
116
+ val (result, codeType) = if (! syncFeature.exchangeKeysToSyncWithAnotherDevice().isEnabled()) {
117
+ Pair (syncAccountRepository.getRecoveryCode(), Recovery )
115
118
} else {
116
- syncAccountRepository.generateExchangeInvitationCode()
117
- }.onSuccess { connectQR ->
118
- barcodeContents = connectQR
119
+ Pair (syncAccountRepository.generateExchangeInvitationCode(), Exchange )
120
+ }
121
+
122
+ result.onSuccess { code ->
123
+ // wrap the code inside a URL if feature flag allows it
124
+ val barcodeString = urlDecorator.decorateCode(code, codeType)
125
+
126
+ barcodeContents = BarcodeContents (underlyingCode = code, barcodeString = barcodeString)
127
+
119
128
val qrBitmap = withContext(dispatchers.io()) {
120
- qrEncoder.encodeAsBitmap(connectQR , dimen.qrSizeSmall, dimen.qrSizeSmall)
129
+ qrEncoder.encodeAsBitmap(barcodeString , dimen.qrSizeSmall, dimen.qrSizeSmall)
121
130
}
131
+
122
132
viewState.emit(viewState.value.copy(qrCodeBitmap = qrBitmap))
123
133
}.onFailure {
124
134
command.send(Command .FinishWithError )
@@ -133,8 +143,8 @@ class SyncWithAnotherActivityViewModel @Inject constructor(
133
143
134
144
fun onCopyCodeClicked () {
135
145
viewModelScope.launch(dispatchers.io()) {
136
- barcodeContents?.let { code ->
137
- clipboard.copyToClipboard(code )
146
+ barcodeContents?.let { contents ->
147
+ clipboard.copyToClipboard(contents.underlyingCode )
138
148
command.send(ShowMessage (string.sync_code_copied_message))
139
149
} ? : command.send(FinishWithError )
140
150
}
@@ -299,4 +309,17 @@ class SyncWithAnotherActivityViewModel @Inject constructor(
299
309
fun onUserAskedToSwitchAccount () {
300
310
syncPixels.fireAskUserToSwitchAccount()
301
311
}
312
+
313
+ private data class BarcodeContents (
314
+ /* *
315
+ * The underlying code that was encoded in the barcode.
316
+ * It's possible this is different from the barcode string which might contain extra data
317
+ */
318
+ val underlyingCode : String ,
319
+
320
+ /* *
321
+ * The string that was encoded in the barcode.
322
+ */
323
+ val barcodeString : String ,
324
+ )
302
325
}
0 commit comments