fix: sync-aware UI for Bitcoin-dependent apps
AppDetails.vue now checks Bitcoin sync progress for LND, ElectrumX, BTCPay, and Mempool. Shows orange warning banner with sync progress bar and block height when Bitcoin is still syncing. Users see clear feedback instead of broken wallet connect pages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -229,6 +229,31 @@
|
||||
<p class="text-white/60 text-sm mt-3 text-center">{{ t('appDetails.screenshotPlaceholder') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Bitcoin Sync Warning (for dependent apps) -->
|
||||
<div v-if="needsBitcoinSync && !bitcoinSynced" class="glass-card p-5 border border-orange-500/30">
|
||||
<div class="flex items-center gap-3 mb-3">
|
||||
<svg class="w-6 h-6 text-orange-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z" />
|
||||
</svg>
|
||||
<div class="flex-1">
|
||||
<p class="text-orange-300 font-semibold text-sm">Bitcoin is syncing</p>
|
||||
<p class="text-white/60 text-xs mt-0.5">
|
||||
Some features may be unavailable until Bitcoin finishes syncing.
|
||||
Wallet connections and block data require a fully synced node.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full h-2 bg-white/10 rounded-full overflow-hidden">
|
||||
<div
|
||||
class="h-full rounded-full bg-orange-400 transition-all duration-500"
|
||||
:style="{ width: Math.min(bitcoinSyncPercent, 100) + '%' }"
|
||||
></div>
|
||||
</div>
|
||||
<p class="text-xs text-white/40 mt-1.5">
|
||||
{{ bitcoinSyncPercent.toFixed(1) }}% synced — Block {{ bitcoinBlockHeight.toLocaleString() }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<div class="glass-card p-6">
|
||||
<h2 class="text-2xl font-bold text-white mb-4">{{ t('appDetails.about', { name: pkg.manifest.title }) }}</h2>
|
||||
@@ -472,7 +497,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useAppStore } from '../stores/app'
|
||||
@@ -480,6 +505,7 @@ import { useAppLauncherStore } from '../stores/appLauncher'
|
||||
import { PackageState } from '../types/api'
|
||||
import { useModalKeyboard } from '@/composables/useModalKeyboard'
|
||||
import { dummyApps } from '../utils/dummyApps'
|
||||
import rpcClient from '@/api/rpc-client'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
@@ -615,6 +641,32 @@ const gatewayState = computed(() => {
|
||||
return gw ? gw.state : 'not installed'
|
||||
})
|
||||
|
||||
/** Apps that depend on Bitcoin being synced */
|
||||
const BITCOIN_DEPENDENT_APPS = ['lnd', 'electrumx', 'electrs', 'mempool-electrs', 'btcpay-server', 'btcpayserver']
|
||||
const needsBitcoinSync = computed(() => BITCOIN_DEPENDENT_APPS.includes(packageKey.value))
|
||||
const bitcoinSyncPercent = ref(0)
|
||||
const bitcoinBlockHeight = ref(0)
|
||||
const bitcoinSynced = computed(() => bitcoinSyncPercent.value >= 99.9)
|
||||
|
||||
async function loadBitcoinSync() {
|
||||
if (!needsBitcoinSync.value) return
|
||||
try {
|
||||
const btc = await rpcClient.call<{ block_height: number; sync_progress: number }>({
|
||||
method: 'bitcoin.getinfo',
|
||||
timeout: 5000,
|
||||
})
|
||||
bitcoinSyncPercent.value = (btc.sync_progress ?? 0) * 100
|
||||
bitcoinBlockHeight.value = btc.block_height ?? 0
|
||||
} catch {
|
||||
bitcoinSyncPercent.value = 0
|
||||
bitcoinBlockHeight.value = 0
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadBitcoinSync()
|
||||
})
|
||||
|
||||
// Action error toast
|
||||
const actionError = ref('')
|
||||
let errorTimer: ReturnType<typeof setTimeout> | undefined
|
||||
|
||||
Reference in New Issue
Block a user