refactor: extract models and utils from nwc

This commit is contained in:
2026-06-10 16:29:11 +02:00
parent 237cc74519
commit 08a76e00d9
3 changed files with 66 additions and 57 deletions
@@ -0,0 +1,48 @@
package com.bitcointxoko.gudariwallet.ui.nwc
import com.bitcointxoko.gudariwallet.api.NwcNewBudget
// ── Available permissions ────────────────────────────────────────────
internal data class NwcPermission(
val serverKey : String, // what we send in the permissions array
val displayLabel : String, // shown in the UI
val default : Boolean // pre-checked by default
)
internal val ALL_PERMISSIONS = listOf(
NwcPermission("pay", "Send payments", default = true),
NwcPermission("invoice", "Create invoices", default = false),
NwcPermission("lookup", "Lookup invoice status", default = false),
NwcPermission("history", "Read transaction history", default = false),
NwcPermission("balance", "Read wallet balance", default = false),
NwcPermission("info", "Read account info", default = false)
)
// ── Budget ────────────────────────────────────────────────────────────
/**
* Transient UI state for a single budget row in the "Add connection" sheet.
* Converted to [NwcNewBudget] on submit.
*/
enum class BudgetRefreshWindow(val label: String, val seconds: Int) {
DAILY ("Daily", 86_400),
WEEKLY ("Weekly", 604_800),
MONTHLY ("Monthly", 2_592_000),
YEARLY ("Yearly", 31_536_000),
NEVER ("Never", 0);
}
data class BudgetDraft(
val id : Int = 0, // stable key for LazyColumn / forEach
val amountSats : String = "", // raw text field value (sats)
val refreshWindow : BudgetRefreshWindow = BudgetRefreshWindow.MONTHLY
) {
/** Returns null when the amount field is blank or non-numeric. */
fun toNwcNewBudget(): NwcNewBudget? {
val sats = amountSats.trim().toLongOrNull()?.takeIf { it > 0 } ?: return null
return NwcNewBudget(
budget_msats = sats * 1_000L,
refresh_window = refreshWindow.seconds
)
}
}
@@ -38,58 +38,10 @@ import com.bitcointxoko.gudariwallet.ui.receive.QrDisplayCard
import com.bitcointxoko.gudariwallet.ui.theme.semanticColors
import java.text.SimpleDateFormat
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import java.util.Calendar
import java.util.Locale
import androidx.core.net.toUri
// ── Available permissions ─────────────────────────────────────────────────────
internal data class NwcPermission(
val serverKey : String, // what we send in the permissions array
val displayLabel : String, // shown in the UI
val default : Boolean // pre-checked by default
)
internal val ALL_PERMISSIONS = listOf(
NwcPermission("pay", "Send payments", default = true),
NwcPermission("invoice", "Create invoices", default = false),
NwcPermission("lookup", "Lookup invoice status", default = false),
NwcPermission("history", "Read transaction history", default = false),
NwcPermission("balance", "Read wallet balance", default = false),
NwcPermission("info", "Read account info", default = false)
)
// ── Budget ────────────────────────────────────────────────────────────────────
/**
* Transient UI state for a single budget row in the "Add connection" sheet.
* Converted to [NwcNewBudget] on submit.
*/
enum class BudgetRefreshWindow(val label: String, val seconds: Int) {
DAILY ("Daily", 86_400),
WEEKLY ("Weekly", 604_800),
MONTHLY ("Monthly", 2_592_000),
YEARLY ("Yearly", 31_536_000),
NEVER ("Never", 0);
}
data class BudgetDraft(
val id : Int = 0, // stable key for LazyColumn / forEach
val amountSats : String = "", // raw text field value (sats)
val refreshWindow : BudgetRefreshWindow = BudgetRefreshWindow.MONTHLY
) {
/** Returns null when the amount field is blank or non-numeric. */
fun toNwcNewBudget(): NwcNewBudget? {
val sats = amountSats.trim().toLongOrNull()?.takeIf { it > 0 } ?: return null
return NwcNewBudget(
budget_msats = sats * 1_000L,
refresh_window = refreshWindow.seconds
)
}
}
// ── Screen ────────────────────────────────────────────────────────────────────
@OptIn(ExperimentalMaterial3Api::class)
@@ -829,12 +781,3 @@ private fun NwcErrorContent(message: String, onRetry: () -> Unit, modifier: Modi
OutlinedButton(onClick = onRetry) { Text("Retry") }
}
}
// ── Helpers ───────────────────────────────────────────────────────────────────
private val dateFormatter: DateTimeFormatter =
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
.withZone(ZoneId.systemDefault())
fun formatEpoch(epochSeconds: Long): String =
runCatching { dateFormatter.format(Instant.ofEpochSecond(epochSeconds)) }.getOrDefault("")
@@ -0,0 +1,18 @@
package com.bitcointxoko.gudariwallet.ui.nwc
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
// ── Date / time formatting ────────────────────────────────────────────
internal val dateFormatter: DateTimeFormatter =
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
.withZone(ZoneId.systemDefault())
/** Formats an epoch-seconds timestamp into a localized human-readable string.
* Returns "—" if the timestamp cannot be formatted. */
internal fun formatEpoch(epochSeconds: Long): String =
runCatching { dateFormatter.format(Instant.ofEpochSecond(epochSeconds)) }
.getOrDefault("")