diff --git a/Bitkit/Components/TabBar/TabBar.swift b/Bitkit/Components/TabBar/TabBar.swift index 43d8386c..8029d1e5 100644 --- a/Bitkit/Components/TabBar/TabBar.swift +++ b/Bitkit/Components/TabBar/TabBar.swift @@ -3,6 +3,7 @@ import SwiftUI struct TabBar: View { @EnvironmentObject var navigation: NavigationViewModel @EnvironmentObject var sheets: SheetViewModel + @EnvironmentObject var wallet: WalletViewModel var shouldShow: Bool { if navigation.activeDrawerMenuItem == .wallet || navigation.activeDrawerMenuItem == .activity { @@ -54,7 +55,11 @@ struct TabBar: View { } private func onReceivePress() { - if navigation.currentRoute == .spendingWallet { + let hasInboundCapacity = (wallet.totalInboundLightningSats ?? 0) > 0 + let hasPendingTransfersToSpending = wallet.balanceInTransferToSpending > 0 + + if navigation.currentRoute == .spendingWallet && !hasInboundCapacity && !hasPendingTransfersToSpending { + // On spending wallet screen, show CJIT flow when user can't receive normally sheets.showSheet(.receive, data: ReceiveConfig(view: .cjitAmount)) } else { sheets.showSheet(.receive) diff --git a/Bitkit/Services/LightningService.swift b/Bitkit/Services/LightningService.swift index 24788cb5..93a77136 100644 --- a/Bitkit/Services/LightningService.swift +++ b/Bitkit/Services/LightningService.swift @@ -728,6 +728,16 @@ extension LightningService { } return (trusted: trusted, nonTrusted: nonTrusted) } + + /// Get a channel by ID from the channel cache + /// This is more reliable than using the cachedChannels array when handling events, + /// as the channelCache is updated immediately when channel events occur + func getChannelFromCache(channelId: ChannelId) async -> ChannelDetails? { + let channelIdString = channelId.description + return await MainActor.run { + channelCache[channelIdString] + } + } } // MARK: Events diff --git a/Bitkit/ViewModels/AppViewModel.swift b/Bitkit/ViewModels/AppViewModel.swift index 3f9791bd..3fbaf910 100644 --- a/Bitkit/ViewModels/AppViewModel.swift +++ b/Bitkit/ViewModels/AppViewModel.swift @@ -684,9 +684,10 @@ extension AppViewModel { // Only relevant for channels to external nodes break case .channelReady(let channelId, userChannelId: _, counterpartyNodeId: _, fundingTxo: _): - if let channel = lightningService.channels?.first(where: { $0.channelId == channelId }) { - Task { - let cjitOrder = try await CoreService.shared.blocktank.getCjit(channel: channel) + Task { + // Use channelCache instead of cachedChannels array, as it's updated immediately + if let channel = await lightningService.getChannelFromCache(channelId: channelId) { + let cjitOrder = await CoreService.shared.blocktank.getCjit(channel: channel) if cjitOrder != nil { let amount = channel.balanceOnCloseSats let now = UInt64(Date().timeIntervalSince1970) @@ -713,7 +714,9 @@ extension AppViewModel { sheetViewModel.showSheet(.receivedTx, data: ReceivedTxSheetDetails(type: .lightning, sats: amount)) } } else { - let channelCount = lightningService.channels?.count ?? 0 + let channelCount = await MainActor.run { + lightningService.channels?.count ?? 0 + } if channelCount == 1 { toast( type: .lightning, @@ -724,17 +727,20 @@ extension AppViewModel { ) } } - } - } else { - let channelCount = lightningService.channels?.count ?? 0 - if channelCount == 1 { - toast( - type: .lightning, - title: t("lightning__channel_opened_title"), - description: t("lightning__channel_opened_msg"), - visibilityTime: 5.0, - accessibilityIdentifier: "SpendingBalanceReadyToast" - ) + } else { + Logger.warn("Channel not found in cache: \(channelId)") + let channelCount = await MainActor.run { + lightningService.channels?.count ?? 0 + } + if channelCount == 1 { + toast( + type: .lightning, + title: t("lightning__channel_opened_title"), + description: t("lightning__channel_opened_msg"), + visibilityTime: 5.0, + accessibilityIdentifier: "SpendingBalanceReadyToast" + ) + } } } case .channelClosed(channelId: _, userChannelId: _, counterpartyNodeId: _, reason: _):