Add privacy and accounts sheets for SEPA.

This commit is contained in:
Alex Hart
2023-10-06 11:38:42 -04:00
committed by Cody Henthorne
parent 4968db750b
commit d2240f07d8
9 changed files with 252 additions and 85 deletions

View File

@@ -29,7 +29,6 @@ import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@@ -53,7 +52,6 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.donate.Do
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.stripe.StripePaymentInProgressViewModel
import org.thoughtcrime.securesms.compose.ComposeFragment
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
import org.thoughtcrime.securesms.util.CommunicationActions
import org.thoughtcrime.securesms.util.SpanUtil
import org.thoughtcrime.securesms.util.fragments.requireListener
import org.thoughtcrime.securesms.util.navigation.safeNavigate
@@ -97,7 +95,8 @@ class BankTransferDetailsFragment : ComposeFragment() {
onNameChanged = viewModel::onNameChanged,
onIBANChanged = viewModel::onIBANChanged,
onEmailChanged = viewModel::onEmailChanged,
onFindAccountNumbersClicked = this::onFindAccountNumbersClicked,
setDisplayFindAccountInfoSheet = viewModel::setDisplayFindAccountInfoSheet,
onLearnMoreClick = this::onLearnMoreClick,
onDonateClick = this::onDonateClick,
onIBANFocusChanged = viewModel::onIBANFocusChanged,
donateLabel = donateLabel
@@ -108,8 +107,10 @@ class BankTransferDetailsFragment : ComposeFragment() {
findNavController().popBackStack()
}
private fun onFindAccountNumbersClicked() {
// TODO [sepa] -- FindAccountNumbersBottomSheet
private fun onLearnMoreClick() {
findNavController().safeNavigate(
BankTransferDetailsFragmentDirections.actionBankTransferDetailsFragmentToYourInformationIsPrivateBottomSheet()
)
}
private fun onDonateClick() {
@@ -129,13 +130,15 @@ private fun BankTransferDetailsContentPreview() {
SignalTheme {
BankTransferDetailsContent(
state = BankTransferDetailsState(
name = "Miles Morales"
name = "Miles Morales",
displayFindAccountInfoSheet = true
),
onNavigationClick = {},
onNameChanged = {},
onIBANChanged = {},
onEmailChanged = {},
onFindAccountNumbersClicked = {},
setDisplayFindAccountInfoSheet = {},
onLearnMoreClick = {},
onDonateClick = {},
onIBANFocusChanged = {},
donateLabel = "Donate $5/month"
@@ -150,7 +153,8 @@ private fun BankTransferDetailsContent(
onNameChanged: (String) -> Unit,
onIBANChanged: (String) -> Unit,
onEmailChanged: (String) -> Unit,
onFindAccountNumbersClicked: () -> Unit,
setDisplayFindAccountInfoSheet: (Boolean) -> Unit,
onLearnMoreClick: () -> Unit,
onDonateClick: () -> Unit,
onIBANFocusChanged: (Boolean) -> Unit,
donateLabel: String
@@ -178,12 +182,11 @@ private fun BankTransferDetailsContent(
item {
val learnMore = stringResource(id = R.string.BankTransferDetailsFragment__learn_more)
val fullString = stringResource(id = R.string.BankTransferDetailsFragment__enter_your_bank_details, learnMore)
val context = LocalContext.current
Texts.LinkifiedText(
textWithUrlSpans = SpanUtil.urlSubsequence(fullString, learnMore, stringResource(id = R.string.donate_url)), // TODO [alex] -- final URL
onUrlClick = {
CommunicationActions.openBrowserLink(context, it)
onLearnMoreClick()
},
style = MaterialTheme.typography.bodyLarge.copy(
color = MaterialTheme.colorScheme.onSurfaceVariant
@@ -276,9 +279,9 @@ private fun BankTransferDetailsContent(
modifier = Modifier.fillMaxWidth()
) {
TextButton(
onClick = onFindAccountNumbersClicked
onClick = { setDisplayFindAccountInfoSheet(true) }
) {
Text(text = stringResource(id = R.string.BankTransferDetailsFragment__find_account_numbers))
Text(text = stringResource(id = R.string.BankTransferDetailsFragment__find_account_info))
}
}
}
@@ -294,6 +297,10 @@ private fun BankTransferDetailsContent(
Text(text = donateLabel)
}
if (state.displayFindAccountInfoSheet) {
FindAccountInfoSheet { setDisplayFindAccountInfoSheet(false) }
}
LaunchedEffect(Unit) {
focusRequester.requestFocus()
}

View File

@@ -11,7 +11,8 @@ data class BankTransferDetailsState(
val name: String = "",
val iban: String = "",
val email: String = "",
val ibanValidity: IBANValidator.Validity = IBANValidator.Validity.POTENTIALLY_VALID
val ibanValidity: IBANValidator.Validity = IBANValidator.Validity.POTENTIALLY_VALID,
val displayFindAccountInfoSheet: Boolean = false
) {
val canProceed = name.isNotEmpty() && email.isNotEmpty() && ibanValidity == IBANValidator.Validity.COMPLETELY_VALID

View File

@@ -18,6 +18,12 @@ class BankTransferDetailsViewModel : ViewModel() {
private val internalState = mutableStateOf(BankTransferDetailsState())
val state: State<BankTransferDetailsState> = internalState
fun setDisplayFindAccountInfoSheet(displayFindAccountInfoSheet: Boolean) {
internalState.value = internalState.value.copy(
displayFindAccountInfoSheet = displayFindAccountInfoSheet
)
}
fun onNameChanged(name: String) {
internalState.value = internalState.value.copy(
name = name

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.details
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import org.signal.core.ui.BottomSheets
import org.thoughtcrime.securesms.R
/**
* Displays a modal bottom sheet that explains where to find the information necessary to perform
* a bank transfer.
*/
@Composable
@OptIn(ExperimentalMaterial3Api::class)
fun FindAccountInfoSheet(
onDismissRequest: () -> Unit
) {
ModalBottomSheet(
onDismissRequest = onDismissRequest,
dragHandle = { BottomSheets.Handle() }
) {
Image(
painter = painterResource(id = R.drawable.find_account_info),
contentDescription = null,
modifier = Modifier
.align(CenterHorizontally)
.padding(vertical = 32.dp)
)
Text(
text = stringResource(id = R.string.FindAccountInfoSheet__find_your_account_information),
style = MaterialTheme.typography.titleLarge,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 60.dp)
.align(CenterHorizontally)
)
Text(
text = stringResource(id = R.string.FindAccountInfoSheet__look_for_your_iban),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.padding(top = 12.dp, bottom = 48.dp, start = 60.dp, end = 60.dp)
.align(CenterHorizontally)
)
}
}

View File

@@ -7,7 +7,6 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.donate.t
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
@@ -24,7 +23,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
@@ -40,7 +38,6 @@ import org.signal.core.ui.Texts
import org.signal.core.ui.theme.SignalTheme
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.compose.ComposeFragment
import org.thoughtcrime.securesms.util.CommunicationActions
import org.thoughtcrime.securesms.util.SpanUtil
import org.thoughtcrime.securesms.util.navigation.safeNavigate
@@ -59,7 +56,14 @@ class BankTransferMandateFragment : ComposeFragment() {
BankTransferScreen(
bankMandate = mandate,
onNavigationClick = this::onNavigationClick,
onContinueClick = this::onContinueClick
onContinueClick = this::onContinueClick,
onLearnMoreClick = this::onLearnMoreClick
)
}
private fun onLearnMoreClick() {
findNavController().safeNavigate(
BankTransferMandateFragmentDirections.actionBankTransferMandateFragmentToYourInformationIsPrivateBottomSheet()
)
}
@@ -81,7 +85,8 @@ fun BankTransferScreenPreview() {
BankTransferScreen(
bankMandate = "Test ".repeat(500),
onNavigationClick = {},
onContinueClick = {}
onContinueClick = {},
onLearnMoreClick = {}
)
}
}
@@ -90,24 +95,19 @@ fun BankTransferScreenPreview() {
fun BankTransferScreen(
bankMandate: String,
onNavigationClick: () -> Unit,
onContinueClick: () -> Unit
onContinueClick: () -> Unit,
onLearnMoreClick: () -> Unit
) {
Scaffolds.Settings(
title = "",
onNavigationClick = onNavigationClick,
navigationIconPainter = rememberVectorPainter(ImageVector.vectorResource(id = R.drawable.symbol_arrow_left_24))
) {
Column(
horizontalAlignment = CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
) {
LazyColumn(
horizontalAlignment = CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.fillMaxHeight()
.padding(top = 64.dp)
) {
item {
@@ -135,12 +135,11 @@ fun BankTransferScreen(
item {
val learnMore = stringResource(id = R.string.BankTransferMandateFragment__learn_more)
val fullString = stringResource(id = R.string.BankTransferMandateFragment__stripe_processes_donations, learnMore)
val context = LocalContext.current
Texts.LinkifiedText(
textWithUrlSpans = SpanUtil.urlSubsequence(fullString, learnMore, stringResource(id = R.string.donate_url)), // TODO [alex] -- final URL
onUrlClick = {
CommunicationActions.openBrowserLink(context, it)
onLearnMoreClick()
},
style = MaterialTheme.typography.bodyLarge.copy(
color = MaterialTheme.colorScheme.onSurfaceVariant
@@ -160,8 +159,8 @@ fun BankTransferScreen(
modifier = Modifier.padding(horizontal = 32.dp, vertical = 16.dp)
)
}
}
item {
Buttons.LargeTonal(
onClick = onContinueClick,
modifier = Modifier
@@ -173,3 +172,4 @@ fun BankTransferScreen(
}
}
}
}

View File

@@ -0,0 +1,66 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="148dp"
android:height="148dp"
android:viewportWidth="148"
android:viewportHeight="148">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M11 26c0-4.42 3.58-8 8-8h111c4.42 0 8 3.58 8 8v96c0 4.42-3.58 8-8 8H19c-4.42 0-8-3.58-8-8V26Z"/>
<path
android:fillColor="#FF2C58C3"
android:pathData="M106.5 90c17.81 0 30.5-11.16 30.5-23s-12.69-23-30.5-23C88.69 44 76 55.16 76 67s12.69 23 30.5 23Zm0 4C87.45 94 72 81.91 72 67s15.45-27 34.5-27S141 52.09 141 67s-15.45 27-34.5 27Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M41.15 41.42l7.36 4.65c0.27 0.16 0.45 0.46 0.45 0.8 0 0.51-0.42 0.93-0.93 0.93H30.28c-0.52 0-0.94-0.42-0.94-0.93 0-0.34 0.18-0.64 0.45-0.8l7.37-4.65c1.21-0.77 2.77-0.77 3.99 0Zm-1 1.58l4.65 2.93H33.5L38.15 43c0.61-0.39 1.39-0.39 2 0Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M30.74 57.61c-0.51 0-0.93 0.42-0.93 0.94 0 0.51 0.42 0.93 0.93 0.93h16.82c0.52 0 0.93-0.42 0.93-0.93 0-0.52-0.41-0.94-0.93-0.94H30.74Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M32.03 50.02v5.37H31.9c-0.45 0-0.82 0.37-0.82 0.82 0 0.45 0.37 0.82 0.82 0.82h1.87c0.45 0 0.82-0.37 0.82-0.82 0-0.45-0.37-0.82-0.82-0.82h-0.12v-5.37h0.12c0.45 0 0.82-0.36 0.82-0.82 0-0.45-0.37-0.81-0.82-0.81H31.9c-0.45 0-0.82 0.36-0.82 0.81 0 0.46 0.37 0.82 0.82 0.82h0.12Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M36.23 55.4v-5.38h-0.12c-0.45 0-0.81-0.36-0.81-0.82 0-0.45 0.36-0.81 0.81-0.81h1.87c0.46 0 0.82 0.36 0.82 0.81 0 0.46-0.36 0.82-0.82 0.82h-0.11v5.37h0.11c0.46 0 0.82 0.37 0.82 0.82 0 0.45-0.36 0.82-0.82 0.82h-1.87c-0.45 0-0.81-0.37-0.81-0.82 0-0.45 0.36-0.82 0.81-0.82h0.12Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M40.44 50.02v5.37h-0.12c-0.45 0-0.82 0.37-0.82 0.82 0 0.45 0.37 0.82 0.82 0.82h1.87c0.45 0 0.82-0.37 0.82-0.82 0-0.45-0.37-0.82-0.82-0.82h-0.12v-5.37h0.12c0.45 0 0.82-0.36 0.82-0.82 0-0.45-0.37-0.81-0.82-0.81h-1.87c-0.45 0-0.82 0.36-0.82 0.81 0 0.46 0.37 0.82 0.82 0.82h0.12Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M44.64 55.4v-5.38h-0.12c-0.45 0-0.81-0.36-0.81-0.82 0-0.45 0.36-0.81 0.81-0.81h1.87c0.45 0 0.82 0.36 0.82 0.81 0 0.46-0.37 0.82-0.82 0.82h-0.11v5.37h0.11c0.45 0 0.82 0.37 0.82 0.82 0 0.45-0.37 0.82-0.82 0.82h-1.87c-0.45 0-0.81-0.37-0.81-0.82 0-0.45 0.36-0.82 0.81-0.82h0.12Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M88 59c0-1.1 0.9-2 2-2h30c1.1 0 2 0.9 2 2s-0.9 2-2 2H90c-1.1 0-2-0.9-2-2Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M88 68c0-1.1 0.9-2 2-2h30c1.1 0 2 0.9 2 2s-0.9 2-2 2H90c-1.1 0-2-0.9-2-2Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M91 75c-1.1 0-2 0.9-2 2s0.9 2 2 2h1c1.1 0 2-0.9 2-2s-0.9-2-2-2h-1Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M96 77c0-1.1 0.9-2 2-2h1c1.1 0 2 0.9 2 2s-0.9 2-2 2h-1c-1.1 0-2-0.9-2-2Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M105 75c-1.1 0-2 0.9-2 2s0.9 2 2 2h1c1.1 0 2-0.9 2-2s-0.9-2-2-2h-1Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M110 77c0-1.1 0.9-2 2-2h1c1.1 0 2 0.9 2 2s-0.9 2-2 2h-1c-1.1 0-2-0.9-2-2Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M119 75c-1.1 0-2 0.9-2 2s0.9 2 2 2h1c1.1 0 2-0.9 2-2s-0.9-2-2-2h-1Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M27 98c0-1.1 0.9-2 2-2h91c1.1 0 2 0.9 2 2s-0.9 2-2 2H29c-1.1 0-2-0.9-2-2Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M29 105c-1.1 0-2 0.9-2 2s0.9 2 2 2h91c1.1 0 2-0.9 2-2s-0.9-2-2-2H29Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M27 116c0-1.1 0.9-2 2-2h91c1.1 0 2 0.9 2 2s-0.9 2-2 2H29c-1.1 0-2-0.9-2-2Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M29 66c-1.1 0-2 0.9-2 2s0.9 2 2 2h20c1.1 0 2-0.9 2-2s-0.9-2-2-2H29Z"/>
<path
android:fillColor="#FFA7B1C9"
android:pathData="M27 77c0-1.1 0.9-2 2-2h19c1.1 0 2 0.9 2 2s-0.9 2-2 2H29c-1.1 0-2-0.9-2-2Z"/>
</vector>

View File

@@ -221,6 +221,9 @@
<action
android:id="@+id/action_bankTransferMandateFragment_to_bankTransferDetailsFragment"
app:destination="@id/bankTransferDetailsFragment" />
<action
android:id="@+id/action_bankTransferMandateFragment_to_yourInformationIsPrivateBottomSheet"
app:destination="@id/yourInformationIsPrivateBottomSheet" />
</fragment>
<fragment
@@ -235,6 +238,9 @@
<action
android:id="@+id/action_bankTransferDetailsFragment_to_stripePaymentInProgressFragment"
app:destination="@id/stripePaymentInProgressFragment" />
<action
android:id="@+id/action_bankTransferDetailsFragment_to_yourInformationIsPrivateBottomSheet"
app:destination="@id/yourInformationIsPrivateBottomSheet" />
</fragment>
</navigation>

View File

@@ -202,6 +202,9 @@
<action
android:id="@+id/action_bankTransferMandateFragment_to_bankTransferDetailsFragment"
app:destination="@id/bankTransferDetailsFragment" />
<action
android:id="@+id/action_bankTransferMandateFragment_to_yourInformationIsPrivateBottomSheet"
app:destination="@id/yourInformationIsPrivateBottomSheet" />
</fragment>
<fragment
@@ -213,5 +216,11 @@
android:name="request"
app:argType="org.thoughtcrime.securesms.components.settings.app.subscription.donate.gateway.GatewayRequest"
app:nullable="false" />
<action
android:id="@+id/action_bankTransferDetailsFragment_to_stripePaymentInProgressFragment"
app:destination="@id/stripePaymentInProgressFragment" />
<action
android:id="@+id/action_bankTransferDetailsFragment_to_yourInformationIsPrivateBottomSheet"
app:destination="@id/yourInformationIsPrivateBottomSheet" />
</fragment>
</navigation>

View File

@@ -5840,7 +5840,7 @@
<!-- Text field label for email -->
<string name="BankTransferDetailsFragment__email">Email</string>
<!-- Text label for button to show user how to find their IBAN number -->
<string name="BankTransferDetailsFragment__find_account_numbers">Find account numbers</string>
<string name="BankTransferDetailsFragment__find_account_info">Find account info</string>
<!-- Donate button label for monthly subscription -->
<string name="BankTransferDetailsFragment__donate_s_month">Donate %1$s/month</string>
<!-- Donate button label for one-time -->
@@ -5854,6 +5854,11 @@
<!-- Error label for IBAN field when number is invalid -->
<string name="BankTransferDetailsFragment__invalid_iban_nubmer">Invalid IBAN number</string>
<!-- Title of bottom sheet for finding account information -->
<string name="FindAccountInfoSheet__find_your_account_information">Find your account information</string>
<!-- Body of bottom sheet for finding account information -->
<string name="FindAccountInfoSheet__look_for_your_iban">Look for your IBAN number at the top of your bank statement. IBAN numbers contain up to 32 characters. The name you enter should match your full name on your bank account. Contact your bank for more information.</string>
<!-- StripePaymentInProgressFragment -->
<string name="StripePaymentInProgressFragment__cancelling">Cancelling…</string>