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:
co-authored by
Claude Opus 4.6
parent
851d8001d6
commit
623c0fa954
@@ -103,6 +103,13 @@ export interface BlockHeader {
|
||||
announced_by: string
|
||||
}
|
||||
|
||||
export interface NodePosition {
|
||||
lat: number
|
||||
lng: number
|
||||
label?: string
|
||||
timestamp: string
|
||||
}
|
||||
|
||||
export const useMeshStore = defineStore('mesh', () => {
|
||||
const status = ref<MeshStatus | null>(null)
|
||||
const peers = ref<MeshPeer[]>([])
|
||||
@@ -111,6 +118,9 @@ export const useMeshStore = defineStore('mesh', () => {
|
||||
const error = ref<string | null>(null)
|
||||
const sending = ref(false)
|
||||
|
||||
// Node position tracking for map view (contact_id -> position)
|
||||
const nodePositions = ref<Map<number, NodePosition>>(new Map())
|
||||
|
||||
// Track unread message counts per peer (contact_id -> count)
|
||||
const unreadCounts = ref<Record<number, number>>({})
|
||||
// Currently viewing chat for this contact_id (clears unread)
|
||||
@@ -161,11 +171,72 @@ export const useMeshStore = defineStore('mesh', () => {
|
||||
}
|
||||
}
|
||||
messages.value = res.messages
|
||||
// Extract node positions from coordinate messages
|
||||
updateNodePositionsFromMessages(res.messages)
|
||||
} catch (err: unknown) {
|
||||
error.value = err instanceof Error ? err.message : 'Failed to fetch mesh messages'
|
||||
}
|
||||
}
|
||||
|
||||
// Convert microdegrees (from mesh protocol) to degrees for Leaflet
|
||||
// Values > 90 for lat or > 180 for lng indicate microdegrees
|
||||
function toDegreesIfMicro(lat: number, lng: number): { lat: number; lng: number } {
|
||||
if (Math.abs(lat) > 90 || Math.abs(lng) > 180) {
|
||||
return { lat: lat / 1000000, lng: lng / 1000000 }
|
||||
}
|
||||
return { lat, lng }
|
||||
}
|
||||
|
||||
function updateNodePositionsFromMessages(msgs: MeshMessage[]) {
|
||||
for (const msg of msgs) {
|
||||
if (msg.message_type === 'coordinate' && msg.typed_payload) {
|
||||
const payload = msg.typed_payload as CoordinateData
|
||||
if (typeof payload.lat === 'number' && typeof payload.lng === 'number') {
|
||||
const existing = nodePositions.value.get(msg.peer_contact_id)
|
||||
if (!existing || msg.timestamp > existing.timestamp) {
|
||||
const deg = toDegreesIfMicro(payload.lat, payload.lng)
|
||||
nodePositions.value.set(msg.peer_contact_id, {
|
||||
lat: deg.lat,
|
||||
lng: deg.lng,
|
||||
label: payload.label,
|
||||
timestamp: msg.timestamp,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
// Also extract coordinates from alert messages that include location
|
||||
if (msg.message_type === 'alert' && msg.typed_payload) {
|
||||
const payload = msg.typed_payload as AlertData
|
||||
if (payload.coordinate && typeof payload.coordinate.lat === 'number' && typeof payload.coordinate.lng === 'number') {
|
||||
const existing = nodePositions.value.get(msg.peer_contact_id)
|
||||
if (!existing || msg.timestamp > existing.timestamp) {
|
||||
const deg = toDegreesIfMicro(payload.coordinate.lat, payload.coordinate.lng)
|
||||
nodePositions.value.set(msg.peer_contact_id, {
|
||||
lat: deg.lat,
|
||||
lng: deg.lng,
|
||||
label: payload.coordinate.label,
|
||||
timestamp: msg.timestamp,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getNodePositions(): Map<number, NodePosition> {
|
||||
return nodePositions.value
|
||||
}
|
||||
|
||||
// Update self node position from deadman GPS data (contact_id = -1 for self)
|
||||
function updateSelfPosition(lat: number, lng: number, label?: string) {
|
||||
nodePositions.value.set(-1, {
|
||||
lat,
|
||||
lng,
|
||||
label: label ?? 'This Node',
|
||||
timestamp: new Date().toISOString(),
|
||||
})
|
||||
}
|
||||
|
||||
function markChatRead(contactId: number) {
|
||||
viewingChatId.value = contactId
|
||||
delete unreadCounts.value[contactId]
|
||||
@@ -368,6 +439,7 @@ export const useMeshStore = defineStore('mesh', () => {
|
||||
sending,
|
||||
unreadCounts,
|
||||
totalUnread,
|
||||
nodePositions,
|
||||
deadmanStatus,
|
||||
blockHeaders,
|
||||
latestBlockHeight,
|
||||
@@ -385,6 +457,8 @@ export const useMeshStore = defineStore('mesh', () => {
|
||||
sendAlert,
|
||||
getSessionStatus,
|
||||
rotatePrekeys,
|
||||
getNodePositions,
|
||||
updateSelfPosition,
|
||||
fetchDeadmanStatus,
|
||||
configureDeadman,
|
||||
deadmanCheckin,
|
||||
|
||||
Reference in New Issue
Block a user