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

Add institution icon to account picker #8389

Merged
merged 1 commit into from
May 16, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 2 additions & 4 deletions financial-connections/api/financial-connections.api
Original file line number Diff line number Diff line change
Expand Up @@ -313,12 +313,10 @@ public final class com/stripe/android/financialconnections/exception/CustomManua
public final class com/stripe/android/financialconnections/features/accountpicker/ComposableSingletons$AccountPickerScreenKt {
public static final field INSTANCE Lcom/stripe/android/financialconnections/features/accountpicker/ComposableSingletons$AccountPickerScreenKt;
public static field lambda-1 Lkotlin/jvm/functions/Function3;
public static field lambda-2 Lkotlin/jvm/functions/Function3;
public static field lambda-3 Lkotlin/jvm/functions/Function4;
public static field lambda-2 Lkotlin/jvm/functions/Function4;
public fun <init> ()V
public final fun getLambda-1$financial_connections_release ()Lkotlin/jvm/functions/Function3;
public final fun getLambda-2$financial_connections_release ()Lkotlin/jvm/functions/Function3;
public final fun getLambda-3$financial_connections_release ()Lkotlin/jvm/functions/Function4;
public final fun getLambda-2$financial_connections_release ()Lkotlin/jvm/functions/Function4;
}

public final class com/stripe/android/financialconnections/features/accountupdate/AccountUpdateRequiredState$Payload$Creator : android/os/Parcelable$Creator {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ internal class AccountPickerPreviewParameterProvider :
)

private fun multiSelect() = AccountPickerState(
institution = Success(
FinancialConnectionsInstitution(
id = "1",
name = "Institution 1",
url = "Institution 1 url",
featured = false,
featuredOrder = null,
icon = Image(default = ""),
logo = null,
mobileHandoffCapable = false
)
),
payload = Success(
AccountPickerState.Payload(
skipAccountSelection = false,
Expand All @@ -73,6 +85,18 @@ internal class AccountPickerPreviewParameterProvider :
)

private fun singleSelect() = AccountPickerState(
institution = Success(
FinancialConnectionsInstitution(
id = "1",
name = "Institution 1",
url = "Institution 1 url",
featured = false,
featuredOrder = null,
icon = Image(default = ""),
logo = null,
mobileHandoffCapable = false
)
),
payload = Success(
AccountPickerState.Payload(
skipAccountSelection = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.LazyListState
Expand All @@ -34,12 +35,14 @@ import com.stripe.android.financialconnections.features.accountpicker.AccountPic
import com.stripe.android.financialconnections.features.accountpicker.AccountPickerState.SelectionMode
import com.stripe.android.financialconnections.features.accountpicker.AccountPickerState.ViewEffect.OpenUrl
import com.stripe.android.financialconnections.features.common.AccountItem
import com.stripe.android.financialconnections.features.common.InstitutionIcon
import com.stripe.android.financialconnections.features.common.LoadingShimmerEffect
import com.stripe.android.financialconnections.features.common.MerchantDataAccessModel
import com.stripe.android.financialconnections.features.common.MerchantDataAccessText
import com.stripe.android.financialconnections.features.common.NoAccountsAvailableErrorContent
import com.stripe.android.financialconnections.features.common.NoSupportedPaymentMethodTypeAccountsErrorContent
import com.stripe.android.financialconnections.features.common.UnclassifiedErrorContent
import com.stripe.android.financialconnections.model.FinancialConnectionsInstitution
import com.stripe.android.financialconnections.model.PartnerAccount
import com.stripe.android.financialconnections.presentation.Async
import com.stripe.android.financialconnections.presentation.Async.Fail
Expand Down Expand Up @@ -140,85 +143,92 @@ private fun AccountPickerLoaded(
onClickableTextClick: (String) -> Unit,
onSubmit: () -> Unit
) {
val displayablePayload = payload()?.takeIf { it.shouldSkipPane.not() }

LazyLayout(
lazyListState = lazyListState,
verticalArrangement = Arrangement.spacedBy(16.dp),
loading = payload is Loading,
showPillOnSlowLoad = true,
body = {
payload()
?.takeIf { it.shouldSkipPane.not() }
?.let {
loadedContent(
payload = it,
state = state,
onAccountClicked = onAccountClicked
)
} ?: run { loadingContent() }
accountPickerContent(
institution = state.institution(),
payload = displayablePayload,
selectedIds = state.selectedIds,
onAccountClicked = onAccountClicked,
)
},
footer = {
payload()
?.takeIf { it.shouldSkipPane.not() }
?.let {
Footer(
merchantDataAccessModel = it.merchantDataAccess,
onClickableTextClick = onClickableTextClick,
submitEnabled = state.submitEnabled,
submitLoading = state.submitLoading,
onSubmit = onSubmit,
selectedIds = state.selectedIds
)
}
displayablePayload?.let {
Footer(
merchantDataAccessModel = it.merchantDataAccess,
onClickableTextClick = onClickableTextClick,
submitEnabled = state.submitEnabled,
submitLoading = state.submitLoading,
onSubmit = onSubmit,
selectedIds = state.selectedIds
)
}
}

)
}

private fun LazyListScope.loadedContent(
payload: AccountPickerState.Payload,
state: AccountPickerState,
onAccountClicked: (PartnerAccount) -> Unit
private fun LazyListScope.accountPickerContent(
institution: FinancialConnectionsInstitution?,
payload: AccountPickerState.Payload?,
selectedIds: Set<String>,
onAccountClicked: (PartnerAccount) -> Unit,
) {
item {
Text(
modifier = Modifier.fillMaxWidth(),
text = stringResource(
when (payload.selectionMode) {
SelectionMode.Single -> R.string.stripe_account_picker_singleselect_account
SelectionMode.Multiple -> R.string.stripe_account_picker_multiselect_account
}
),
style = FinancialConnectionsTheme.typography.headingXLarge
)
}
items(payload.accounts, key = { it.id }) { account ->
AccountItem(
selected = state.selectedIds.contains(account.id),
showInstitutionIcon = false,
onAccountClicked = onAccountClicked,
account = account,
item("icon") {
InstitutionIcon(
institutionIcon = institution?.icon?.default,
modifier = Modifier.padding(top = 16.dp),
disablePlaceholder = true,
)
}
}

private fun LazyListScope.loadingContent() {
item {
Text(
modifier = Modifier.fillMaxWidth(),
text = "Retrieving accounts",
style = FinancialConnectionsTheme.typography.headingXLarge
)
item("header") {
if (payload != null) {
Text(
modifier = Modifier.fillMaxWidth(),
text = stringResource(
when (payload.selectionMode) {
SelectionMode.Single -> R.string.stripe_account_picker_singleselect_account
SelectionMode.Multiple -> R.string.stripe_account_picker_multiselect_account
}
),
style = FinancialConnectionsTheme.typography.headingXLarge
)
} else {
Text(
modifier = Modifier.fillMaxWidth(),
text = "Retrieving accounts",
style = FinancialConnectionsTheme.typography.headingXLarge
)
}
}
items(3) {
LoadingShimmerEffect {
Box(
modifier = Modifier
.fillMaxWidth()
.height(72.dp)
.clip(RoundedCornerShape(16.dp))
.background(it)

if (payload != null) {
items(payload.accounts, key = { it.id }) { account ->
AccountItem(
selected = selectedIds.contains(account.id),
showInstitutionIcon = false,
onAccountClicked = onAccountClicked,
account = account,
)
}
} else {
items(3) {
LoadingShimmerEffect {
Box(
modifier = Modifier
.fillMaxWidth()
.height(72.dp)
.clip(RoundedCornerShape(16.dp))
.background(it)
)
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import com.stripe.android.financialconnections.features.common.isDataFlow
import com.stripe.android.financialconnections.features.notice.NoticeSheetState.NoticeSheetContent.DataAccess
import com.stripe.android.financialconnections.features.notice.PresentNoticeSheet
import com.stripe.android.financialconnections.model.DataAccessNotice
import com.stripe.android.financialconnections.model.FinancialConnectionsInstitution
import com.stripe.android.financialconnections.model.FinancialConnectionsSessionManifest.Pane
import com.stripe.android.financialconnections.model.PartnerAccount
import com.stripe.android.financialconnections.model.PartnerAccountsList
Expand Down Expand Up @@ -72,6 +73,7 @@ internal class AccountPickerViewModel @AssistedInject constructor(
init {
logErrors()
onPayloadLoaded()
loadInstitution()
loadAccounts()
}

Expand All @@ -83,6 +85,16 @@ internal class AccountPickerViewModel @AssistedInject constructor(
)
}

private fun loadInstitution() {
suspend {
val sync = getOrFetchSync()
val manifest = sync.manifest
requireNotNull(manifest.activeInstitution)
}.execute {
copy(institution = it)
}
}
tillh-stripe marked this conversation as resolved.
Show resolved Hide resolved

private fun loadAccounts() {
suspend {
val state = stateFlow.value
Expand Down Expand Up @@ -376,6 +388,7 @@ internal class AccountPickerViewModel @AssistedInject constructor(
}

internal data class AccountPickerState(
val institution: Async<FinancialConnectionsInstitution> = Uninitialized,
val payload: Async<Payload> = Uninitialized,
val canRetry: Boolean = true,
val selectAccounts: Async<PartnerAccountsList> = Uninitialized,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,34 @@ import com.stripe.android.financialconnections.ui.theme.FinancialConnectionsThem
import com.stripe.android.uicore.image.StripeImage

@Composable
internal fun InstitutionIcon(institutionIcon: String?) {
internal fun InstitutionIcon(
institutionIcon: String?,
modifier: Modifier = Modifier,
disablePlaceholder: Boolean = false,
) {
val previewMode = LocalInspectionMode.current
val iconModifier = Modifier
val iconModifier = modifier
.size(56.dp)
.shadow(1.dp, RoundedCornerShape(12.dp), clip = true)

when {
previewMode || institutionIcon == null -> InstitutionPlaceholder(iconModifier)
else -> StripeImage(
url = institutionIcon,
imageLoader = LocalImageLoader.current,
contentDescription = null,
modifier = iconModifier,
contentScale = ContentScale.Crop,
loadingContent = { Box(modifier = iconModifier.background(colors.backgroundOffset)) },
errorContent = { InstitutionPlaceholder(iconModifier) }
)
institutionIcon == null && disablePlaceholder -> {
Box(modifier = iconModifier.background(colors.backgroundOffset))
}
previewMode || institutionIcon == null -> {
InstitutionPlaceholder(iconModifier)
}
else -> {
StripeImage(
url = institutionIcon,
imageLoader = LocalImageLoader.current,
contentDescription = null,
modifier = iconModifier,
contentScale = ContentScale.Crop,
loadingContent = { Box(modifier = iconModifier.background(colors.backgroundOffset)) },
errorContent = { InstitutionPlaceholder(iconModifier) }
)
}
}
}

Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.