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 @@ -121,7 +121,7 @@ fun EnterAmountView(
color = if (exceedsBalance) CoveColor.WarningOrange else MaterialTheme.colorScheme.onSurface,
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth().offset(x = amountOffset),
modifier = Modifier.fillMaxWidth().padding(horizontal = 30.dp).offset(x = amountOffset),
onTextWidthChanged = { width -> textWidth = width },
onFocusChanged = { focused ->
isFocused = focused
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ fun SendFlowConfirmScreen(
text = stringResource(R.string.action_swipe_to_send),
sendState = sendState,
onComplete = onSwipeToSend,
containerColor = MaterialTheme.colorScheme.surfaceVariant,
containerColor = MaterialTheme.coveColors.swipeTrackBg,
targetContainerColor = MaterialTheme.coveColors.midnightBtn,
knobColor = MaterialTheme.coveColors.midnightBtn,
textColor = MaterialTheme.colorScheme.onSurface,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ private fun SendFlowRouteToScreen(
val exceedsBalance = sendFlowManager.rust.amountExceedsBalance()
var previouslyExceeded by remember { mutableStateOf(false) }
val snackbarHostState = remember { SnackbarHostState() }
val validationScope = rememberCoroutineScope()

LaunchedEffect(exceedsBalance) {
if (exceedsBalance && !previouslyExceeded) {
Expand All @@ -229,8 +230,39 @@ private fun SendFlowRouteToScreen(
snackbarHostState = snackbarHostState,
onBack = { app.popRoute() },
onNext = {
if (sendFlowManager.validate(displayAlert = true)) {
sendFlowManager.dispatch(SendFlowManagerAction.FinalizeAndGoToNextScreen)
val addressValid = sendFlowManager.rust.validateAddress()
val amountValid = sendFlowManager.rust.validateAmount()
val hasAddress = sendFlowManager.enteringAddress.isNotEmpty()
val hasAmount = sendFlowManager.rust.amount().asSats() > 0uL

when {
!addressValid -> {
// only show snackbar if address has content (not just empty)
if (hasAddress) {
validationScope.launch {
snackbarHostState.showSnackbar(
message = "Address not valid. Please try again.",
duration = SnackbarDuration.Short,
)
}
}
presenter.focusField = SetAmountFocusField.ADDRESS
}
!amountValid -> {
// only show snackbar if amount has content (not just empty/zero)
if (hasAmount) {
validationScope.launch {
snackbarHostState.showSnackbar(
message = "Amount not valid. Please try again.",
duration = SnackbarDuration.Short,
)
}
}
presenter.focusField = SetAmountFocusField.AMOUNT
}
else -> {
sendFlowManager.dispatch(SendFlowManagerAction.FinalizeAndGoToNextScreen)
}
}
},
onScanQr = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ object CoveColor {
val coveBgDark = ComposeColor(0xFF191919)
val midnightBtnDark = ComposeColor(0xFF4A4A4D)

// Swipe track background (matches iOS systemGray5)
val swipeTrackBgLight = ComposeColor(0xFFE5E5EA)
val swipeTrackBgDark = ComposeColor(0xFF2C2C2E)

// Wallet colors - pastel palette (preferred)
val beige = ComposeColor(0xFFFFB36E)
val lightMint = ComposeColor(0xFFC5E5CD)
Expand Down Expand Up @@ -80,18 +84,21 @@ object CoveColor {
data class CoveColorScheme(
val midnightBtn: ComposeColor,
val systemGreen: ComposeColor,
val swipeTrackBg: ComposeColor,
)

val LightCoveColors =
CoveColorScheme(
midnightBtn = CoveColor.midnightBlue, // #1C2536
systemGreen = CoveColor.SystemGreenLight, // #34C759
swipeTrackBg = CoveColor.swipeTrackBgLight, // #E5E5EA (iOS systemGray5)
)

val DarkCoveColors =
CoveColorScheme(
midnightBtn = CoveColor.midnightBtnDark, // #4A4A4D
systemGreen = CoveColor.SystemGreenDark, // #30D158
swipeTrackBg = CoveColor.swipeTrackBgDark, // #2C2C2E (iOS systemGray5)
)

val LocalCoveColors = staticCompositionLocalOf { LightCoveColors }
Expand Down
40 changes: 37 additions & 3 deletions ios/Cove/Flows/SendFlow/SendFlowSetAmountScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,51 @@ struct SendFlowSetAmountScreen: View {

// MARK: Actions

// validate, create final psbt and send to next screen
private func next() {
if validate(true) { sendFlowManager.dispatch(action: .finalizeAndGoToNextScreen) }
Task {
guard await performValidation() else { return }
sendFlowManager.dispatch(action: .finalizeAndGoToNextScreen)
}
}

private func dismissIfValid() {
if validate(true) {
Task {
guard await performValidation() else { return }
presenter.focusField = .none
}
}

private func performValidation() async -> Bool {
if !validateAddress() {
if !address.wrappedValue.isEmpty {
await FloaterPopup(
text: "Address not valid. Please try again.",
backgroundColor: .orange,
textColor: .white,
iconColor: .white,
icon: "exclamationmark.triangle"
).dismissAfter(1).present()
}
presenter.focusField = .address
return false
}
if !validateAmount() {
let hasAmount = sendFlowManager.amount != nil && sendFlowManager.amount?.asSats() != 0
if hasAmount {
await FloaterPopup(
text: "Amount not valid. Please try again.",
backgroundColor: .orange,
textColor: .white,
iconColor: .white,
icon: "exclamationmark.triangle"
).dismissAfter(1).present()
}
presenter.focusField = .amount
return false
}
return true
}

// doing it this way prevents an alert popping up when the user just goes back
private func setAlertState(_ error: SendFlowError) {
sendFlowManager.presenter.alertState = .init(.error(error))
Expand Down