Skip to content

Commit 388c669

Browse files
authored
Merge branch 'master' into fix/msat-invoice-precision
2 parents 5d7614d + e9619ee commit 388c669

29 files changed

Lines changed: 1052 additions & 225 deletions

File tree

AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ suspend fun getData(): Result<Data> = withContext(Dispatchers.IO) {
240240

241241
### Changelog
242242

243-
- ALWAYS add an entry under `## [Unreleased]` in `CHANGELOG.md` for `feat:` and `fix:` PRs; skip for `chore:`, `ci:`, `refactor:`, `test:`, `docs:` unless the change is user-facing
243+
- ALWAYS add exactly ONE entry per PR under `## [Unreleased]` in `CHANGELOG.md` for `feat:` and `fix:` PRs; skip for `chore:`, `ci:`, `refactor:`, `test:`, `docs:` unless the change is user-facing
244+
- NEVER add multiple changelog lines for the same PR — summarize all changes in a single concise entry
244245
- USE standard Keep a Changelog categories: `### Added`, `### Changed`, `### Deprecated`, `### Removed`, `### Fixed`, `### Security`
245246
- ALWAYS append `#PR_NUMBER` at the end of each changelog entry when the PR number is known
246247
- ALWAYS place new entries at the top of their category section (newest first)

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2424
- Mnemonic warning text transitions on reveal #857
2525

2626
### Changed
27+
- Unified send flow with payment method switcher, details toggle, Lightning support for BIP21 payments, and improved fee rate defaults #863
2728
- Settings redesigned with tabbed navigation (General/Security/Advanced) with swipe support #857
2829
- Icons added to all settings rows for faster scanning #857
2930
- Selected values displayed on right side of settings rows #857

app/src/main/java/to/bitkit/ext/DateTime.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,34 @@ fun Long.toRelativeTimeString(
109109
}
110110
}
111111

112+
fun formatInvoiceExpiryRelative(
113+
expirySeconds: ULong,
114+
locale: Locale = Locale.getDefault(),
115+
): String {
116+
val seconds = expirySeconds.toLong()
117+
if (seconds <= 0) return ""
118+
119+
val uLocale = ULocale.forLocale(locale)
120+
val numberFormat = NumberFormat.getNumberInstance(uLocale)?.apply { maximumFractionDigits = 0 }
121+
val formatter = RelativeDateTimeFormatter.getInstance(
122+
uLocale,
123+
numberFormat,
124+
RelativeDateTimeFormatter.Style.LONG,
125+
DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,
126+
) ?: return ""
127+
128+
val minutes = seconds / Factor.SECONDS_TO_MINUTES.toLong()
129+
val hours = minutes / Factor.MINUTES_TO_HOURS.toLong()
130+
val days = hours / Factor.HOURS_TO_DAYS.toLong()
131+
132+
return when {
133+
minutes < 1 -> formatter.format(seconds.toDouble(), Direction.NEXT, RelativeUnit.SECONDS)
134+
hours < 1 -> formatter.format(minutes.toDouble(), Direction.NEXT, RelativeUnit.MINUTES)
135+
days < 1 -> formatter.format(hours.toDouble(), Direction.NEXT, RelativeUnit.HOURS)
136+
else -> formatter.format(days.toDouble(), Direction.NEXT, RelativeUnit.DAYS)
137+
}
138+
}
139+
112140
fun getDaysInMonth(month: LocalDate): List<LocalDate?> {
113141
val firstDayOfMonth = LocalDate(month.year, month.month, Constants.FIRST_DAY_OF_MONTH)
114142
val daysInMonth = month.month.toJavaMonth().length(isLeapYear(month.year))

app/src/main/java/to/bitkit/models/FeeRate.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ enum class FeeRate(
1515
@DrawableRes val icon: Int,
1616
val color: Color,
1717
) {
18+
INSTANT(
19+
title = R.string.fee__instant__title,
20+
description = R.string.fee__instant__description,
21+
shortDescription = R.string.fee__instant__shortDescription,
22+
color = Colors.Purple,
23+
icon = R.drawable.ic_speed_fast,
24+
),
1825
FAST(
1926
title = R.string.fee__fast__title,
2027
description = R.string.fee__fast__description,
@@ -53,7 +60,7 @@ enum class FeeRate(
5360

5461
fun toSpeed(): TransactionSpeed {
5562
return when (this) {
56-
FAST -> TransactionSpeed.Fast
63+
INSTANT, FAST -> TransactionSpeed.Fast
5764
NORMAL -> TransactionSpeed.Medium
5865
MINIMUM, SLOW -> TransactionSpeed.Slow
5966
CUSTOM -> TransactionSpeed.Custom(0u)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package to.bitkit.ui.components
2+
3+
import androidx.compose.foundation.layout.Column
4+
import androidx.compose.foundation.layout.fillMaxWidth
5+
import androidx.compose.material3.HorizontalDivider
6+
import androidx.compose.material3.Text
7+
import androidx.compose.runtime.Composable
8+
import androidx.compose.ui.Modifier
9+
import androidx.compose.ui.tooling.preview.Preview
10+
import androidx.compose.ui.unit.dp
11+
import to.bitkit.ui.theme.AppThemeSurface
12+
import to.bitkit.ui.theme.Colors
13+
14+
@Composable
15+
fun SendCell(
16+
caption: String,
17+
modifier: Modifier = Modifier,
18+
content: @Composable () -> Unit,
19+
) {
20+
Column(modifier = modifier.fillMaxWidth()) {
21+
Caption13Up(text = caption, color = Colors.White64)
22+
VerticalSpacer(8.dp)
23+
content()
24+
VerticalSpacer(16.dp)
25+
HorizontalDivider(modifier = Modifier.fillMaxWidth())
26+
}
27+
}
28+
29+
@Preview(showSystemUi = true)
30+
@Composable
31+
private fun Preview() {
32+
AppThemeSurface {
33+
SendCell(caption = "AMOUNT") {
34+
Text("0.001 BTC", color = Colors.White)
35+
}
36+
}
37+
}

app/src/main/java/to/bitkit/ui/components/SwipeToConfirm.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import androidx.compose.material3.Icon
2323
import androidx.compose.material3.Text
2424
import androidx.compose.runtime.Composable
2525
import androidx.compose.runtime.LaunchedEffect
26+
import androidx.compose.runtime.MutableFloatState
27+
import androidx.compose.runtime.SideEffect
2628
import androidx.compose.runtime.getValue
2729
import androidx.compose.runtime.mutableFloatStateOf
2830
import androidx.compose.runtime.mutableStateOf
@@ -61,15 +63,16 @@ private val Padding = 8.dp
6163

6264
@Composable
6365
fun SwipeToConfirm(
66+
onConfirm: () -> Unit,
67+
modifier: Modifier = Modifier,
6468
text: String = stringResource(R.string.other__swipe),
6569
color: Color = Colors.Brand,
6670
icon: ImageVector = Icons.AutoMirrored.Default.ArrowForward,
6771
@DrawableRes endIcon: Int = R.drawable.ic_check,
6872
endIconTint: Color = Colors.Black,
6973
loading: Boolean = false,
7074
confirmed: Boolean = false,
71-
onConfirm: () -> Unit,
72-
modifier: Modifier = Modifier,
75+
progress: MutableFloatState? = null,
7376
) {
7477
val scope = rememberCoroutineScope()
7578
val trailColor = remember(color) { color.copy(alpha = 0.24f) }
@@ -94,6 +97,10 @@ fun SwipeToConfirm(
9497
)
9598
}
9699

100+
SideEffect {
101+
progress?.floatValue = (panX.value / maxPanX).coerceIn(0f, 1f)
102+
}
103+
97104
Box(
98105
modifier = modifier
99106
.requiredHeight(CircleSize + Padding * 2)

0 commit comments

Comments
 (0)