feat: complete Phase 2 transport layer — off-grid mode, transport icons, federation sync

- Add off-grid (mesh only) toggle to Mesh.vue with orange OFF-GRID banner
- Add per-peer transport indicator in Federation.vue (mesh/lan/tor icons)
- Add sync_with_peer_via_transport() for CBOR delta sync via transport router
- Fetch transport store on mount in both Mesh and Federation views

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-17 00:45:37 +00:00
parent 174dad9a66
commit f83e151f5a
3 changed files with 114 additions and 1 deletions

View File

@@ -163,6 +163,11 @@
<div class="flex items-center gap-3 min-w-0">
<div class="w-2.5 h-2.5 rounded-full shrink-0" :class="isOnline(node) ? 'bg-green-400' : 'bg-white/30'"></div>
<span class="text-sm font-medium text-white truncate">{{ node.name || shortDid(node.did) }}</span>
<span
class="text-xs shrink-0"
:class="nodeTransportIcon(node.did).color"
:title="'Transport: ' + nodeTransportIcon(node.did).label"
>{{ nodeTransportIcon(node.did).icon }}</span>
</div>
<span
class="text-xs px-2 py-0.5 rounded-full shrink-0"
@@ -368,9 +373,12 @@
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { rpcClient } from '@/api/rpc-client'
import { useTransportStore } from '@/stores/transport'
import type { TransportPeer } from '@/stores/transport'
import NetworkMap from '@/components/federation/NetworkMap.vue'
const router = useRouter()
const transportStore = useTransportStore()
interface AppStatus {
id: string
@@ -689,9 +697,22 @@ function trustBadgeClass(level: string): string {
}
}
/** Get the preferred transport icon for a federated node by DID. */
function nodeTransportIcon(did: string): { icon: string; color: string; label: string } {
const peer = transportStore.peers.find(p => p.did === did)
if (!peer) return { icon: '?', color: 'text-white/30', label: 'unknown' }
switch (peer.preferred_transport) {
case 'mesh': return { icon: '📡', color: 'text-orange-400', label: 'mesh' }
case 'lan': return { icon: '🌐', color: 'text-green-400', label: 'lan' }
case 'tor': return { icon: '🧅', color: 'text-purple-400', label: 'tor' }
default: return { icon: '?', color: 'text-white/30', label: 'unknown' }
}
}
onMounted(async () => {
loadNodes()
loadDwnStatus()
transportStore.fetchPeers()
try {
const result = await rpcClient.getNodeDid()
selfDid.value = result.did