From 08a76e00d95db0860be2f651b1f8f86108250f98 Mon Sep 17 00:00:00 2001 From: rasputin Date: Wed, 10 Jun 2026 16:29:11 +0200 Subject: [PATCH] refactor: extract models and utils from nwc --- .../gudariwallet/ui/nwc/NwcModels.kt | 48 ++++++++++++++++ .../gudariwallet/ui/nwc/NwcScreen.kt | 57 ------------------- .../gudariwallet/ui/nwc/NwcUtils.kt | 18 ++++++ 3 files changed, 66 insertions(+), 57 deletions(-) create mode 100644 app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcModels.kt create mode 100644 app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcUtils.kt diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcModels.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcModels.kt new file mode 100644 index 0000000..2f0d66a --- /dev/null +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcModels.kt @@ -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 + ) + } +} diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcScreen.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcScreen.kt index 44c0c36..6b9de88 100644 --- a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcScreen.kt +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcScreen.kt @@ -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("—") diff --git a/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcUtils.kt b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcUtils.kt new file mode 100644 index 0000000..384de31 --- /dev/null +++ b/app/src/main/java/com/bitcointxoko/gudariwallet/ui/nwc/NwcUtils.kt @@ -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("—")