Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
961ca84
chore: ReceiveTab enum
jvsena42 Nov 27, 2025
32ff9b4
chore: ReceiveInvoiceUtils
jvsena42 Nov 27, 2025
ac18980
chore: add temporary strings
jvsena42 Nov 27, 2025
dd35520
feat: update CustomTabRowWithSpacing.kt to be generic
jvsena42 Nov 27, 2025
866d3f9
feat: update CustomTabRowWithSpacing.kt to be generic
jvsena42 Nov 27, 2025
7bcffcd
feat: implement tabs WIP
jvsena42 Nov 27, 2025
f1033ad
feat: implement tab WIP
jvsena42 Nov 28, 2025
a9d153e
chore: cleanup code
jvsena42 Nov 28, 2025
771b979
feat: tab color
jvsena42 Nov 28, 2025
1ee8d21
chore: cleanup code
jvsena42 Nov 28, 2025
dd0ef18
feat: copy address visibility
jvsena42 Nov 28, 2025
804dd1e
feat: buttons tab
jvsena42 Nov 28, 2025
f93e271
feat: preview
jvsena42 Nov 28, 2025
e65fa77
feat: detail view background
jvsena42 Nov 28, 2025
ec2469c
feat: qr placeholder
jvsena42 Nov 28, 2025
0eb4fcb
fix: ln invoice extraction
jvsena42 Nov 28, 2025
db352d1
chore: simplify onchain address extraction
jvsena42 Nov 28, 2025
398271e
feat: button detail visibility
jvsena42 Nov 28, 2025
63273d2
fix: qr_placeholder glitch
jvsena42 Nov 28, 2025
58bb34b
chore: clean import
jvsena42 Nov 28, 2025
72f0737
fix: don't reset details on tab change
jvsena42 Nov 28, 2025
ea3e9b8
feat: cjit onboard WIP
jvsena42 Nov 28, 2025
e10b37f
feat: cjit onboard WIP
jvsena42 Nov 28, 2025
2f2a39d
feat: cjit navigation
jvsena42 Nov 28, 2025
8bb0d24
feat: cjit navigation
jvsena42 Nov 28, 2025
eed3ce0
feat: cjit onboarding view
jvsena42 Nov 28, 2025
c6ab634
chore: remove redundant code
jvsena42 Nov 28, 2025
6ce2bd5
fix: filter usable channels
jvsena42 Nov 28, 2025
d8c2f0f
fix: preview
jvsena42 Nov 28, 2025
e023fa2
fix: only display cjit if node is running
jvsena42 Nov 28, 2025
f7f0352
Merge branch 'master' into feat/new-receive-sheet
jvsena42 Nov 28, 2025
79e4d95
Merge branch 'master' into feat/new-receive-sheet
jvsena42 Nov 28, 2025
eeb6818
Merge branch 'master' into feat/new-receive-sheet
jvsena42 Nov 29, 2025
d3818ab
Merge remote-tracking branch 'origin/feat/new-receive-sheet' into fea…
jvsena42 Dec 1, 2025
2b94867
feat: toast geoblocked
jvsena42 Dec 1, 2025
46f3ddf
chore: remove geoblock navigation
jvsena42 Dec 1, 2025
670a67a
feat: implement swipe
jvsena42 Dec 1, 2025
5d7ea5e
chore: reuse variable
jvsena42 Dec 1, 2025
2f5c9c3
refactor replace mutable state with string
jvsena42 Dec 1, 2025
a70d803
fix: display spending as default when cjit invoice is not null
jvsena42 Dec 1, 2025
1f33e00
fix: edit cjit
jvsena42 Dec 1, 2025
c866261
chore: lint
jvsena42 Dec 1, 2025
ccd92a5
chore: lint
jvsena42 Dec 1, 2025
a4cf140
refactor: implement Modifier.node
jvsena42 Dec 1, 2025
777cb6c
refactor: implement Modifier.node
jvsena42 Dec 1, 2025
0b2a052
chore: remove dead parameter
jvsena42 Dec 1, 2025
ceb3739
adjust test tag
piotr-iohk Dec 2, 2025
e018184
Merge branch 'master' into feat/new-receive-sheet
ovitrif Dec 2, 2025
e69e4bd
chore: imports
jvsena42 Dec 2, 2025
805dd54
chore: extract string resources
jvsena42 Dec 2, 2025
74aba74
fix: keep bip 21 onchain info to onchain only payments
jvsena42 Dec 3, 2025
cb641ae
fix: display only address on details
jvsena42 Dec 3, 2025
f0de4de
refactor: replace qr animation with HorizontalPager
jvsena42 Dec 3, 2025
0adec78
chore: lint
jvsena42 Dec 3, 2025
2baacf3
fix: page spacing
jvsena42 Dec 3, 2025
1feffcb
chore: restore geoblocked navigation
jvsena42 Dec 3, 2025
03088e4
fix: remove ripple from tabs
jvsena42 Dec 3, 2025
591d70e
fix: cache invoice
jvsena42 Dec 3, 2025
851200c
fix: detail view weight
jvsena42 Dec 3, 2025
0ecc0d7
fix: restore circular indicator
jvsena42 Dec 3, 2025
ed5a907
refactor: replace horizontal pager wit lazy row
jvsena42 Dec 3, 2025
f44b3c7
fix: restore map
jvsena42 Dec 3, 2025
1e2e856
fix: horizontal spacing
jvsena42 Dec 3, 2025
a3b1c7d
fix: detail button update
jvsena42 Dec 3, 2025
3c70daf
refactor: improve state derivation
jvsena42 Dec 3, 2025
e5716d3
refactor: remove box wrapper
jvsena42 Dec 3, 2025
3c005c8
refactor: extract selection color
jvsena42 Dec 3, 2025
abfabae
chore: imports
jvsena42 Dec 3, 2025
6b08c70
Merge branch 'master' into feat/new-receive-sheet
jvsena42 Dec 4, 2025
7ff1342
fix: remove column horizontal padding
jvsena42 Dec 4, 2025
e9df62a
fix: button padding
jvsena42 Dec 4, 2025
ba46ca2
refactor: simplify code
jvsena42 Dec 4, 2025
ca693a3
fix: prevent from display auto invoice without lightning
jvsena42 Dec 4, 2025
09e6b2e
fix: auto tab color
jvsena42 Dec 4, 2025
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 @@ -100,10 +100,10 @@ fun ActivityListFilter(
}
}

enum class ActivityTab {
enum class ActivityTab : TabItem {
ALL, SENT, RECEIVED, OTHER;

val uiText: String
override val uiText: String
@Composable
get() = when (this) {
ALL -> stringResource(R.string.wallet__activity_tabs__all)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,17 @@
import to.bitkit.ui.components.CaptionB
import to.bitkit.ui.theme.Colors

interface TabItem {
val name: String
val uiText: String
@Composable get
}

@Composable
fun CustomTabRowWithSpacing(
tabs: List<ActivityTab>,
fun <T : TabItem> CustomTabRowWithSpacing(
tabs: List<T>,
currentTabIndex: Int,
onTabChange: (ActivityTab) -> Unit,
onTabChange: (T) -> Unit,
modifier: Modifier = Modifier,
) {
Column(modifier = modifier) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package to.bitkit.ui.screens.wallets.receive

import org.lightningdevkit.ldknode.ChannelDetails
import to.bitkit.R
import to.bitkit.models.NodeLifecycleState

/**
* Strips the Lightning invoice parameter from a BIP21 URI, returning pure onchain address.
*
* Example:
* Input: "bitcoin:bc1q...?amount=0.001&lightning=lnbc..."
* Output: "bitcoin:bc1q...?amount=0.001"
*
* @param bip21 The full BIP21 URI
* @return BIP21 URI without lightning parameter
*/
fun stripLightningFromBip21(bip21: String): String {
if (bip21.isEmpty()) return bip21

// Remove lightning parameter and its value
// Pattern: &lightning=... or ?lightning=...
val lightningParamRegex = Regex("[?&]lightning=[^&]*")
var result = bip21.replace(lightningParamRegex, "")

// If we removed the first param (started with ?), convert & to ?
if (result.contains("&") && !result.contains("?")) {
result = result.replaceFirst("&", "?")
}

// Clean up trailing ? or &
result = result.trimEnd('?', '&')

return result
}

/**
* Returns the appropriate invoice/address for the selected tab.
*
* @param tab The selected receive tab
* @param bip21 Full BIP21 invoice (onchain + lightning)
* @param bolt11 Lightning invoice
* @param cjitInvoice CJIT invoice from Blocktank (if active)
* @param onchainAddress Pure Bitcoin address (fallback)
* @return The invoice string to display/encode in QR
*/
fun getInvoiceForTab(
tab: ReceiveTab,
bip21: String,
bolt11: String,
cjitInvoice: String?,
onchainAddress: String
): String {
return when (tab) {
ReceiveTab.SAVINGS -> {
// Pure onchain: strip lightning from BIP21
val strippedBip21 = stripLightningFromBip21(bip21)
strippedBip21.ifEmpty { onchainAddress }
}
ReceiveTab.AUTO -> {
// Unified: prefer CJIT > full BIP21
cjitInvoice?.takeIf { it.isNotEmpty() }
?: bip21.ifEmpty { onchainAddress }
}
ReceiveTab.SPENDING -> {
// Lightning only: prefer CJIT > bolt11
cjitInvoice?.takeIf { it.isNotEmpty() }
?: bolt11.ifEmpty { onchainAddress }
}
}
}

/**
* Returns the appropriate QR code logo resource for the selected tab.
*
* @param tab The selected receive tab
* @param hasCjit Whether a CJIT invoice is active
* @return Drawable resource ID for QR logo
*/
fun getQrLogoResource(tab: ReceiveTab, hasCjit: Boolean): Int {
return when (tab) {
ReceiveTab.SAVINGS -> R.drawable.ic_btc_circle
ReceiveTab.AUTO -> {
// Unified logo if CJIT or standard unified
if (hasCjit) R.drawable.ic_unified_circle
else R.drawable.ic_unified_circle
}
ReceiveTab.SPENDING -> R.drawable.ic_ln_circle
}
}

/**
* Determines whether the Auto (unified) tab should be visible.
*
* Logic:
* - Node must be running
* - If geoblocked: only show if user has existing channels (grandfathered)
* - If not geoblocked: always show
*
* @param channels List of Lightning channels
* @param isGeoblocked Whether Lightning is geoblocked for this user
* @param nodeRunning Whether the Lightning node is running
* @return true if Auto tab should be visible
*/
fun shouldShowAutoTab(
channels: List<ChannelDetails>,
isGeoblocked: Boolean,
nodeRunning: Boolean
): Boolean {
if (!nodeRunning) return false

return if (isGeoblocked) {
// Geoblocked users can still use Auto if they have existing channels
channels.isNotEmpty()
} else {
// Not geoblocked: always show Auto tab
true
}
}

/**
* Extension: Check if node lifecycle state is running.
*/
fun NodeLifecycleState.isRunning(): Boolean {
return this == NodeLifecycleState.Running
}

/**
* Extension: Check if node lifecycle state is starting.
*/
fun NodeLifecycleState.isStarting(): Boolean {
return this == NodeLifecycleState.Starting
}
Loading
Loading