Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Render FC auth flow in bottom sheet #8443

Merged
merged 1 commit into from
May 21, 2024
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
7 changes: 0 additions & 7 deletions financial-connections/api/financial-connections.api
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@ public final class com/stripe/android/financialconnections/BuildConfig {
public fun <init> ()V
}

public final class com/stripe/android/financialconnections/ComposableSingletons$FinancialConnectionsSheetActivityKt {
public static final field INSTANCE Lcom/stripe/android/financialconnections/ComposableSingletons$FinancialConnectionsSheetActivityKt;
public static field lambda-1 Lkotlin/jvm/functions/Function2;
public fun <init> ()V
public final fun getLambda-1$financial_connections_release ()Lkotlin/jvm/functions/Function2;
}

public final class com/stripe/android/financialconnections/FinancialConnections {
public static final field $stable I
public static final field INSTANCE Lcom/stripe/android/financialconnections/FinancialConnections;
Expand Down
14 changes: 12 additions & 2 deletions financial-connections/res/values/themes.xml
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>

<style name="StripeBaseTheme" parent="@style/Theme.AppCompat.DayNight.NoActionBar">
<style name="StripeFinancialConnectionsBaseTheme" parent="@style/Theme.AppCompat.DayNight.NoActionBar">
<item name="colorAccent">@color/stripe_accent_color_default</item>
<item name="colorControlNormal">@color/stripe_control_normal_color_default</item>
<item name="colorPrimary">@color/stripe_toolbar_color_default</item>
<item name="colorPrimaryDark">@color/stripe_toolbar_color_default_dark</item>
<item name="titleTextColor">@color/stripe_title_text_color</item>
<item name="android:textColorSecondary">@color/stripe_text_color_secondary</item>
<item name="android:windowIsTranslucent">true</item>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding these attributes into the base theme, just like PaymentSheet.

<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="windowNoTitle">true</item>
<item name="android:windowAnimationStyle">@null</item>
</style>

<style name="StripeDefaultTheme" parent="StripeBaseTheme" />
<style name="StripeFinancialConnectionsDefaultTheme" parent="StripeFinancialConnectionsBaseTheme">
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
</resources>
4 changes: 2 additions & 2 deletions financial-connections/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@
<activity
android:name=".FinancialConnectionsSheetActivity"
android:exported="false"
android:theme="@style/StripeDefaultTheme" />
android:theme="@style/StripeFinancialConnectionsDefaultTheme" />

<activity
android:name="com.stripe.android.financialconnections.ui.FinancialConnectionsSheetNativeActivity"
android:exported="false"
android:windowSoftInputMode="adjustResize"
android:theme="@style/StripeDefaultTheme" />
android:theme="@style/StripeFinancialConnectionsDefaultTheme" />
</application>

<!--
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.widget.Toast
import androidx.activity.addCallback
import androidx.activity.compose.BackHandler
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.activity.viewModels
Expand All @@ -14,15 +14,13 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.stripe.android.financialconnections.FinancialConnectionsSheetViewEffect.FinishWithResult
import com.stripe.android.financialconnections.FinancialConnectionsSheetViewEffect.OpenAuthFlowWithUrl
import com.stripe.android.financialconnections.FinancialConnectionsSheetViewEffect.OpenNativeAuthFlow
Expand All @@ -32,11 +30,10 @@ import com.stripe.android.financialconnections.launcher.FinancialConnectionsShee
import com.stripe.android.financialconnections.launcher.FinancialConnectionsSheetActivityResult
import com.stripe.android.financialconnections.launcher.FinancialConnectionsSheetNativeActivityArgs
import com.stripe.android.financialconnections.ui.FinancialConnectionsSheetNativeActivity
import com.stripe.android.financialconnections.ui.components.FinancialConnectionsBottomSheetLayout
import com.stripe.android.financialconnections.ui.theme.FinancialConnectionsTheme
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import com.stripe.android.uicore.elements.bottomsheet.StripeBottomSheetState
import com.stripe.android.uicore.elements.bottomsheet.rememberStripeBottomSheetState

internal class FinancialConnectionsSheetActivity : AppCompatActivity() {

Expand All @@ -56,32 +53,55 @@ internal class FinancialConnectionsSheetActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (getArgs(intent) == null) {

val args = getArgs(intent)
if (args == null) {
finish()
} else {
observeViewEffects()
browserManager = BrowserManager(application)
if (savedInstanceState != null) viewModel.onActivityRecreated()
return
}

onBackPressedDispatcher.addCallback {
finishWithResult(FinancialConnectionsSheetActivityResult.Canceled)
browserManager = BrowserManager(application)

if (savedInstanceState != null) {
viewModel.onActivityRecreated()
}

setContent {
val bottomSheetState = rememberStripeBottomSheetState()
val state by viewModel.stateFlow.collectAsState()
Loading(state.isInstantDebits)

LaunchedEffect(state.viewEffect) {
state.viewEffect?.let { viewEffect ->
handleViewEffect(
viewEffect = viewEffect,
bottomSheetState = bottomSheetState,
)
viewModel.onViewEffectLaunched()
}
}

BackHandler {
viewModel.onDismissed()
}

FinancialConnectionsTheme(state.isInstantDebits) {
FinancialConnectionsBottomSheetLayout(
state = bottomSheetState,
onDismissed = viewModel::onDismissed,
) {
Loading()
}
}
}
}

@Composable
private fun Loading(instantDebits: Boolean) {
FinancialConnectionsTheme(instantDebits = instantDebits) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
LoadingSpinner(Modifier.size(52.dp))
}
private fun Loading() {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
LoadingSpinner(Modifier.size(52.dp))
}
}

Expand All @@ -98,39 +118,30 @@ internal class FinancialConnectionsSheetActivity : AppCompatActivity() {
viewModel.handleOnNewIntent(intent)
}

/**
* handle state changes here.
*/
private suspend fun handleViewEffect(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the view effect handling here to allow it to be called from Compose.

viewEffect: FinancialConnectionsSheetViewEffect,
bottomSheetState: StripeBottomSheetState,
) {
when (viewEffect) {
is OpenAuthFlowWithUrl -> {
startBrowserForResult.launch(
browserManager.createBrowserIntentForUrl(
uri = Uri.parse(viewEffect.url)
)
)
}

private fun observeViewEffects() = lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.stateFlow
.map { it.viewEffect }
.distinctUntilChanged()
.filterNotNull()
.collect { viewEffect ->
when (viewEffect) {
is OpenAuthFlowWithUrl -> startBrowserForResult.launch(
browserManager.createBrowserIntentForUrl(
uri = Uri.parse(viewEffect.url)
)
)

is FinishWithResult -> {
viewEffect.finishToast?.let { resId ->
Toast.makeText(
this@FinancialConnectionsSheetActivity,
resId,
Toast.LENGTH_LONG
).show()
}
finishWithResult(viewEffect.result)
}

is OpenNativeAuthFlow -> openNativeAuthFlow(viewEffect)
}
viewModel.onViewEffectLaunched()
is FinishWithResult -> {
viewEffect.finishToast?.let { resId ->
Toast.makeText(this, resId, Toast.LENGTH_LONG).show()
}
bottomSheetState.hide()
finishWithResult(viewEffect.result)
}

is OpenNativeAuthFlow -> {
openNativeAuthFlow(viewEffect)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ internal class FinancialConnectionsSheetViewModel @Inject constructor(
private val analyticsTracker: FinancialConnectionsAnalyticsTracker,
private val nativeRouter: NativeAuthFlowRouter,
nativeAuthFlowCoordinator: NativeAuthFlowCoordinator,
initialState: FinancialConnectionsSheetState
initialState: FinancialConnectionsSheetState,
) : FinancialConnectionsViewModel<FinancialConnectionsSheetState>(initialState, nativeAuthFlowCoordinator) {

private val mutex = Mutex()
Expand Down Expand Up @@ -130,7 +130,7 @@ internal class FinancialConnectionsSheetViewModel @Inject constructor(
val manifest = sync.manifest
val isInstantDebits = stateFlow.value.isInstantDebits
val nativeAuthFlowEnabled = nativeRouter.nativeAuthFlowEnabled(manifest, isInstantDebits)
viewModelScope.launch { nativeRouter.logExposure(manifest, isInstantDebits) }
nativeRouter.logExposure(manifest, isInstantDebits)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drive-by fix: This doesn’t need to be suspending anymore.

val hostedAuthUrl = buildHostedAuthUrl(manifest.hostedAuthUrl, isInstantDebits)
if (hostedAuthUrl == null) {
finishWithResult(
Expand Down Expand Up @@ -212,6 +212,13 @@ internal class FinancialConnectionsSheetViewModel @Inject constructor(
}
}

fun onDismissed() {
finishWithResult(
state = stateFlow.value,
result = Canceled
)
}

/**
* If activity resumes and we did not receive a callback from the custom tabs,
* then the user hit the back button or closed the custom tabs UI, so return result as
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal class NativeAuthFlowRouter @Inject constructor(
return isInstantDebits.not() && killSwitchEnabled.not() && nativeExperimentEnabled
}

suspend fun logExposure(
fun logExposure(
manifest: FinancialConnectionsSessionManifest,
isInstantDebits: Boolean,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,14 @@ import com.stripe.android.financialconnections.navigation.topappbar.TopAppBarHos
import com.stripe.android.financialconnections.presentation.FinancialConnectionsSheetNativeViewEffect.Finish
import com.stripe.android.financialconnections.presentation.FinancialConnectionsSheetNativeViewEffect.OpenUrl
import com.stripe.android.financialconnections.presentation.FinancialConnectionsSheetNativeViewModel
import com.stripe.android.financialconnections.ui.components.FinancialConnectionsBottomSheetLayout
import com.stripe.android.financialconnections.ui.components.FinancialConnectionsModalBottomSheetLayout
import com.stripe.android.financialconnections.ui.components.FinancialConnectionsScaffold
import com.stripe.android.financialconnections.ui.components.FinancialConnectionsTopAppBar
import com.stripe.android.financialconnections.ui.theme.FinancialConnectionsTheme
import com.stripe.android.financialconnections.utils.KeyboardController
import com.stripe.android.financialconnections.utils.rememberKeyboardController
import com.stripe.android.uicore.elements.bottomsheet.rememberStripeBottomSheetState
import com.stripe.android.uicore.image.StripeImageLoader
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.distinctUntilChanged
Expand Down Expand Up @@ -98,10 +100,19 @@ internal class FinancialConnectionsSheetNativeActivity : AppCompatActivity() {
setContent {
FinancialConnectionsTheme {
val state by viewModel.stateFlow.collectAsState()
NavHost(
initialPane = state.initialPane,
testMode = state.testMode,
val bottomSheetState = rememberStripeBottomSheetState(
initialValue = ModalBottomSheetValue.Expanded,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We launch this expanded, because FinancialConnectionsSheetActivity is already open.

)

FinancialConnectionsBottomSheetLayout(
state = bottomSheetState,
onDismissed = viewModel::onBackPressed,
) {
NavHost(
initialPane = state.initialPane,
testMode = state.testMode,
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,56 @@
package com.stripe.android.financialconnections.ui.components

import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.stripe.android.financialconnections.navigation.bottomsheet.BottomSheetNavigator
import com.stripe.android.financialconnections.navigation.bottomsheet.ModalBottomSheetLayout
import com.stripe.android.financialconnections.ui.theme.FinancialConnectionsTheme.colors
import com.stripe.android.financialconnections.ui.theme.Neutral900
import com.stripe.android.uicore.elements.bottomsheet.StripeBottomSheetLayout
import com.stripe.android.uicore.elements.bottomsheet.StripeBottomSheetLayoutInfo
import com.stripe.android.uicore.elements.bottomsheet.StripeBottomSheetState
import com.stripe.android.uicore.elements.bottomsheet.rememberStripeBottomSheetLayoutInfo

@Composable
internal fun FinancialConnectionsBottomSheetLayout(
state: StripeBottomSheetState,
modifier: Modifier = Modifier,
onDismissed: () -> Unit,
content: @Composable () -> Unit,
) {
val layoutInfo = rememberFinancialConnectionsBottomSheetLayoutInfo()

StripeBottomSheetLayout(
state = state,
layoutInfo = layoutInfo,
modifier = modifier,
onDismissed = onDismissed,
sheetContent = content,
)
}

@Composable
internal fun FinancialConnectionsModalBottomSheetLayout(
bottomSheetNavigator: BottomSheetNavigator,
content: @Composable () -> Unit
) {
com.stripe.android.financialconnections.navigation.bottomsheet.ModalBottomSheetLayout(
val layoutInfo = rememberFinancialConnectionsBottomSheetLayoutInfo()

ModalBottomSheetLayout(
bottomSheetNavigator = bottomSheetNavigator,
sheetBackgroundColor = layoutInfo.sheetBackgroundColor,
sheetShape = layoutInfo.sheetShape,
scrimColor = layoutInfo.scrimColor,
content = content,
)
}

@Composable
private fun rememberFinancialConnectionsBottomSheetLayoutInfo(): StripeBottomSheetLayoutInfo {
return rememberStripeBottomSheetLayoutInfo(
cornerRadius = 20.dp,
sheetBackgroundColor = colors.backgroundSurface,
sheetShape = RoundedCornerShape(20.dp, 20.dp, 0.dp, 0.dp),
scrimColor = Neutral900.copy(alpha = 0.32f),
content = content,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,7 @@ internal fun FinancialConnectionsTheme(
SideEffect {
window?.let { window ->
val insets = WindowCompat.getInsetsController(window, view)
window.statusBarColor = barColor.toArgb()
window.navigationBarColor = barColor.toArgb()
insets.isAppearanceLightStatusBars = true
insets.isAppearanceLightNavigationBars = true
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal fun FinancialConnectionsSessionManifest.experimentAssignment(
experiment: Experiment
): String? = experimentAssignments?.get(experiment.key)

internal suspend fun FinancialConnectionsAnalyticsTracker.trackExposure(
internal fun FinancialConnectionsAnalyticsTracker.trackExposure(
experiment: Experiment,
manifest: FinancialConnectionsSessionManifest
) {
Expand Down
Loading
Loading