Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,14 @@ class PaymentRepository @Inject constructor(
messagingRepository.rejectLogin(rendezvousKey)
}

fun attemptRequest(payload: CodePayload): Pair<KinAmount, CodePayload>? {
suspend fun attemptRequest(payload: CodePayload): Pair<KinAmount, CodePayload>? {
val fiat = payload.fiat
if (fiat == null) {
Timber.d("payload does not contain Fiat value")
return null
}

exchange.fetchRatesIfNeeded()
val rate = exchange.rateFor(fiat.currency)
if (rate == null) {
Timber.d("Unable to determine rate")
Expand Down
10 changes: 8 additions & 2 deletions app/src/main/java/com/getcode/util/DeeplinkHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,13 @@ class DeeplinkHandler @Inject constructor() {

fun checkIntent(intent: Intent): Intent? {
Timber.d("checking intent=${intent.data}")
handle(intent) ?: return null
return intent
val uri = intent.data ?: return null
return when (uri.deeplinkType) {
is Type.Cash,
is Type.Login,
is Type.Sdk -> intent
is Type.Unknown -> null
}
}

fun handle(intent: Intent? = debounceIntent): Pair<Type, List<Screen>>? {
Expand All @@ -48,6 +53,7 @@ class DeeplinkHandler @Inject constructor() {
}

is Type.Cash -> {
Timber.d("cash=${type.link}")
type to listOf(HomeScreen(cashLink = type.link))
}

Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/com/getcode/view/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ class MainActivity : FragmentActivity() {
handleUncaughtException()
authManager.init(this)
setFullscreen()
deeplinkHandler.debounceIntent = deeplinkHandler.checkIntent(intent)

setContent {
CompositionLocalProvider(
Expand All @@ -98,6 +97,8 @@ class MainActivity : FragmentActivity() {
CodeApp()
}
}

deeplinkHandler.debounceIntent = intent
}

override fun onResume() {
Expand Down
10 changes: 6 additions & 4 deletions app/src/main/java/com/getcode/view/camera/KikCodeScannerView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.functions.BiFunction
import io.reactivex.rxjava3.processors.BehaviorProcessor
import kotlinx.coroutines.flow.Flow
import org.kin.sdk.base.tools.Optional

class KikCodeScannerView @JvmOverloads constructor(
Expand All @@ -16,7 +17,7 @@ class KikCodeScannerView @JvmOverloads constructor(
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

private var previewing = false
var previewing = false

private val cameraController: CameraController = LegacyCameraController(context)

Expand Down Expand Up @@ -44,9 +45,10 @@ class KikCodeScannerView @JvmOverloads constructor(
cameraController.startPreview()

previewSizeSubscription = Flowable
.combineLatest(cameraController.previewSize(), onLayoutChangeSubject.distinctUntilChanged(), BiFunction { previewSize: Optional<CameraController.PreviewSize>, _: Pair<Int, Int> ->
previewSize
})
.combineLatest(
cameraController.previewSize(),
onLayoutChangeSubject.distinctUntilChanged()
) { previewSize: Optional<CameraController.PreviewSize>, _: Pair<Int, Int> -> previewSize }
.filter { it.isPresent }
.observeOn(UiThreadScheduler.uiThread())
.subscribe {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import android.graphics.Rect
import android.hardware.Camera
import android.media.CamcorderProfile
import android.media.MediaRecorder
import android.util.Log
import android.view.Surface
import android.view.SurfaceHolder
import android.view.SurfaceView
Expand All @@ -21,7 +20,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.kin.sdk.base.tools.Optional
import timber.log.Timber
import java.lang.IllegalStateException
import java.net.URL
import kotlin.math.abs
import kotlin.math.max
Expand Down Expand Up @@ -562,7 +560,7 @@ class LegacyCameraController(
return Single.fromCallable {
val videoOutputUrl = videoOutputUrl
val mediaRecorder = mediaRecorder
val recordingStart = recordingStartSubject.value!!.get()!!
val recordingStart = recordingStartSubject.value!!.get()

this@LegacyCameraController.videoOutputUrl = null
this@LegacyCameraController.mediaRecorder = null
Expand Down
65 changes: 35 additions & 30 deletions app/src/main/java/com/getcode/view/components/AuthCheck.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ import com.getcode.navigation.screens.LoginScreen
import com.getcode.util.DeeplinkHandler
import com.getcode.util.getActivity
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
Expand All @@ -50,23 +55,24 @@ fun AuthCheck(
}

LaunchedEffect(isAuthenticated) {
Timber.tag(AUTH_NAV).d("authenticated=$isAuthenticated")
isAuthenticated?.let { authenticated ->
//Allow the seed input screen to complete and avoid
//premature navigation
if (currentRoute is AccessKeyLoginScreen) {
Timber.tag(AUTH_NAV).d("No navigation within seed input")
return@LaunchedEffect
}
if (currentRoute is LoginGraph) {
Timber.tag(AUTH_NAV).d("No navigation within account creation and onboarding")
} else if (!deeplinkRouted) {
if (authenticated) {
Timber.tag(AUTH_NAV).d("Navigating to home")
onNavigate(listOf(HomeScreen()), false)
} else {
Timber.tag(AUTH_NAV).d("Navigating to login")
onNavigate(listOf(LoginScreen()), false)
if (!deeplinkRouted) {
// Allow the seed input screen to complete and avoid
// premature navigation
if (currentRoute is AccessKeyLoginScreen) {
log("No navigation within seed input")
return@LaunchedEffect
}
if (currentRoute is LoginGraph) {
log("No navigation within account creation and onboarding")
} else {
if (authenticated) {
log("Navigating to home")
onNavigate(listOf(HomeScreen()), false)
} else {
log("Navigating to login")
onNavigate(listOf(LoginScreen()), false)
}
}
} else {
deeplinkRouted = false
Expand All @@ -81,23 +87,21 @@ fun AuthCheck(
val scope = this
deeplinkHandler.intent
.filterNotNull()
.onEach {
deeplinkRouted = false
Timber.tag(AUTH_NAV).d("intent=${it.data}")
}
.distinctUntilChanged()
.mapNotNull { deeplinkHandler.handle() }
.onEach { Timber.d("${it.first}") }
.filter {
if (it.first is DeeplinkHandler.Type.Cash) {
return@filter SessionManager.isAuthenticated() == true
.flatMapLatest { combine(flowOf(it), SessionManager.authState) { a, b -> a to b } }
.filter { (data, authState) ->
if (data.first is DeeplinkHandler.Type.Cash || data.first is DeeplinkHandler.Type.Sdk) {
return@filter authState.isAuthenticated == true
}
return@filter true
}
.mapNotNull { (type, screens) ->
.mapNotNull { (data, auth) ->
val (type, screens) = data
if (type is DeeplinkHandler.Type.Login) {
if (SessionManager.isAuthenticated() == true) {
if (auth.isAuthenticated == true) {
val entropy = (screens.first() as? LoginScreen)?.seed
Timber.d("showing logout confirm")
log("showing logout confirm")
if (entropy != null) {
deeplinkRouted = true
context.getActivity()?.intent = null
Expand All @@ -107,7 +111,7 @@ fun AuthCheck(
entropyB64 = entropy,
onSwitchAccounts = {
scope.launch {
delay(300)
delay(300) // wait for dismiss
onSwitchAccounts(it)
deeplinkRouted = false
}
Expand All @@ -124,15 +128,17 @@ fun AuthCheck(
}
.onEach { screens ->
deeplinkRouted = true
log("navigated")
onNavigate(screens, true)
deeplinkHandler.debounceIntent = null
context.getActivity()?.intent = null
deeplinkRouted = false
}
.launchIn(this)
}
}

private fun log(message: String) = Timber.tag(AUTH_NAV).d(message)

private fun showLogoutMessage(
context: Context,
entropyB64: String,
Expand All @@ -142,7 +148,6 @@ private fun showLogoutMessage(
BottomBarManager.showMessage(
BottomBarManager.BottomBarMessage(
title = context.getString(R.string.subtitle_logoutAndLoginConfirmation),
subtitle = "",
positiveText = context.getString(R.string.action_logIn),
negativeText = context.getString(R.string.action_cancel),
isDismissible = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import com.getcode.theme.CodeTheme
import com.getcode.theme.White10
import com.getcode.util.getActivity
import com.getcode.util.rememberedClickable
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

@Composable
Expand Down Expand Up @@ -80,8 +81,11 @@ fun AccountHome(
positiveText = context.getString(R.string.action_logout),
negativeText = context.getString(R.string.action_cancel),
onPositive = {
context.getActivity()?.let {
viewModel.logout(it)
composeScope.launch {
delay(150) // wait for dismiss
context.getActivity()?.let {
viewModel.logout(it)
}
}
}
)
Expand Down
47 changes: 19 additions & 28 deletions app/src/main/java/com/getcode/view/main/home/HomeScan.kt
Original file line number Diff line number Diff line change
Expand Up @@ -160,32 +160,38 @@ private fun HomeScan(

var kikCodeScannerView: KikCodeScannerView? by remember { mutableStateOf(null) }


val focusManager = LocalFocusManager.current
LaunchedEffect(dataState.isCameraScanEnabled) {
if (dataState.isCameraScanEnabled) {
focusManager.clearFocus()
}
}

LaunchedEffect(homeViewModel) {
if (!deepLink.isNullOrBlank()) {
homeViewModel.onCashLinkGrabStart()
}
if (!deepLink.isNullOrBlank() && !dataState.isDeepLinkHandled) {
homeViewModel.openCashLink(deepLink)
LaunchedEffect(kikCodeScannerView?.previewing, deepLink, requestPayload) {
if (kikCodeScannerView?.previewing == true) {
if (!deepLink.isNullOrBlank()) {
delay(1_000)
homeViewModel.openCashLink(deepLink)
}

if (!requestPayload.isNullOrBlank()) {
delay(1_000)
homeViewModel.handlePaymentRequest(requestPayload)
}
}
}

if (!requestPayload.isNullOrBlank()) {
delay(500)
homeViewModel.handlePaymentRequest(requestPayload)
LaunchedEffect(kikCodeScannerView?.previewing) {
val view = kikCodeScannerView ?: return@LaunchedEffect
if (view.previewing) { // kick off preview scanning once preview established
homeViewModel.startScan(view)
}
}

fun startScanPreview() {
val view = kikCodeScannerView ?: return
// establish preview
view.startPreview()
homeViewModel.startScan(view)
}

fun stopScanPreview() {
Expand Down Expand Up @@ -225,7 +231,7 @@ private fun HomeScan(
update = { }
)
},
isCameraReady = dataState.isCameraReady,
isCameraReady = kikCodeScannerView?.previewing == true,
showBottomSheet = { showBottomSheet(it) }
)

Expand Down Expand Up @@ -270,11 +276,6 @@ private fun HomeScan(
homeViewModel.stopScan()
}
}
LaunchedEffect(dataState.isCameraScanEnabled) {
if (dataState.isCameraScanEnabled) {
startScanPreview()
}
}

val context = LocalContext.current as Activity
LaunchedEffect(dataState.billState.bill) {
Expand All @@ -301,7 +302,6 @@ private fun BillContainer(

val launcher = getPermissionLauncher(onPermissionResult)
val context = LocalContext.current as Activity
val composeScope = rememberCoroutineScope()

SideEffect {
PermissionCheck.requestPermission(
Expand All @@ -322,13 +322,9 @@ private fun BillContainer(
if (dataState.isCameraPermissionGranted == true || dataState.isCameraPermissionGranted == null) {
scannerView()

var show by rememberSaveable {
mutableStateOf(true)
}

AnimatedVisibility(
modifier = Modifier.fillMaxSize(),
visible = show,
visible = !isCameraReady,
enter = fadeIn(
animationSpec = tween(AnimationUtils.animationTime)
),
Expand All @@ -339,11 +335,6 @@ private fun BillContainer(
.fillMaxSize()
.background(CodeTheme.colors.background)
)
LaunchedEffect(isCameraReady) {
if (isCameraReady) {
show = false
}
}
}
} else {
PermissionsBlockingView(
Expand Down
Loading