feat: Discover view, Fleet dashboard, MeshMap, type fixes

- New Discover.vue (app store redesign)
- Fleet.vue dashboard for .228
- MeshMap.vue component
- Fixed Discover.vue type errors (unused var, type predicate)
- Various UI updates (Apps, Dashboard, Marketplace, Mesh, Web5)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-19 16:12:01 +00:00
parent 9b4aa712f2
commit f20f0650cf
18 changed files with 3067 additions and 174 deletions

View File

@@ -5,6 +5,7 @@ import { useTransportStore } from '@/stores/transport'
import type { MeshPeer, SessionStatus } from '@/stores/mesh'
import AnimatedLogo from '@/components/AnimatedLogo.vue'
import ToggleSwitch from '@/components/ToggleSwitch.vue'
import MeshMap from '@/components/MeshMap.vue'
import { rpcClient } from '@/api/rpc-client'
const mesh = useMeshStore()
@@ -38,7 +39,7 @@ const togglingOffGrid = ref(false)
const peerSessionInfo = ref<SessionStatus | null>(null)
// Phase 4: Off-grid Bitcoin + Dead Man's Switch
const activeTab = ref<'chat' | 'bitcoin' | 'deadman'>('chat')
const activeTab = ref<'chat' | 'bitcoin' | 'deadman' | 'map'>('chat')
const txHexInput = ref('')
const bolt11Input = ref('')
const bolt11AmountInput = ref('')
@@ -55,7 +56,7 @@ const deadmanEnabled = ref(false)
const deadmanCustomMsg = ref('')
// Tools tab for 3rd column on wide desktop and mobile below-chat
const toolsTab = ref<'bitcoin' | 'deadman'>('bitcoin')
const toolsTab = ref<'bitcoin' | 'deadman' | 'map'>('bitcoin')
// Panel visibility computeds
const showChatPanel = computed(() =>
@@ -70,6 +71,10 @@ const showDeadmanPanel = computed(() => {
if (isWideDesktop.value || (isMobile.value && !mobileShowChat.value)) return toolsTab.value === 'deadman'
return activeTab.value === 'deadman'
})
const showMapPanel = computed(() => {
if (isWideDesktop.value || (isMobile.value && !mobileShowChat.value)) return toolsTab.value === 'map'
return activeTab.value === 'map'
})
// Mobile tools: show on first view (peers), hide when in chat
const showMobileTools = computed(() => isMobile.value && !mobileShowChat.value)
// Medium desktop: show 3-tab bar. Wide + mobile: hidden (tools has own tab bar)
@@ -548,6 +553,10 @@ function truncatePubkey(hex: string | null): string {
Dead Man
<span v-if="mesh.deadmanStatus?.triggered" class="mesh-tab-badge mesh-tab-badge-alert">!</span>
</button>
<button class="mesh-tab" :class="{ active: activeTab === 'map' }" @click="activeTab = 'map'">
Map
<span v-if="mesh.nodePositions.size > 0" class="mesh-tab-badge">{{ mesh.nodePositions.size }}</span>
</button>
</div>
<!-- Chat Panel (before tools so it gets grid-column 2 on wide) -->
@@ -673,8 +682,15 @@ function truncatePubkey(hex: string | null): string {
Dead Man
<span v-if="mesh.deadmanStatus?.triggered" class="mesh-tab-badge mesh-tab-badge-alert">!</span>
</button>
<button class="mesh-tab" :class="{ active: toolsTab === 'map' }" @click="toolsTab = 'map'">
Map
<span v-if="mesh.nodePositions.size > 0" class="mesh-tab-badge">{{ mesh.nodePositions.size }}</span>
</button>
</div>
<!-- Map Panel -->
<div v-if="showMapPanel" class="glass-card mesh-map-panel"><MeshMap /></div>
<!-- Off-Grid Bitcoin Panel -->
<div v-if="showBitcoinPanel" class="glass-card mesh-bitcoin-panel">
<h3 class="mesh-panel-title">Off-Grid Bitcoin</h3>
@@ -839,7 +855,12 @@ function truncatePubkey(hex: string | null): string {
Dead Man
<span v-if="mesh.deadmanStatus?.triggered" class="mesh-tab-badge mesh-tab-badge-alert">!</span>
</button>
<button class="mesh-tab" :class="{ active: toolsTab === 'map' }" @click="toolsTab = 'map'">
Map
<span v-if="mesh.nodePositions.size > 0" class="mesh-tab-badge">{{ mesh.nodePositions.size }}</span>
</button>
</div>
<div v-if="showMapPanel" class="glass-card mesh-map-panel"><MeshMap /></div>
<div v-if="showBitcoinPanel" class="glass-card mesh-bitcoin-panel">
<!-- Reuse same content via a shared approach - for now inline -->
<h3 class="mesh-panel-title">Off-Grid Bitcoin</h3>
@@ -1646,6 +1667,10 @@ function truncatePubkey(hex: string | null): string {
min-height: 320px;
}
.mesh-mobile-tools .mesh-map-panel {
min-height: 400px;
}
.mesh-status-grid {
grid-template-columns: repeat(2, 1fr);
}
@@ -1878,6 +1903,16 @@ function truncatePubkey(hex: string | null): string {
.mesh-relay-result.success { background: rgba(74,222,128,0.1); color: #4ade80; border: 1px solid rgba(74,222,128,0.2); }
.mesh-relay-result.error { background: rgba(239,68,68,0.1); color: #ef4444; border: 1px solid rgba(239,68,68,0.2); }
/* ─── Map panel ─── */
.mesh-map-panel {
flex: 1;
min-height: 400px;
padding: 0 !important; /* Override glass-card padding */
overflow: hidden;
border-radius: 12px;
position: relative;
}
/* ─── Dead Man panel ─── */
.mesh-deadman-panel {
display: flex;