feat(ui): mesh header "Flash LoRa" button opens the in-app flash flow
Demo images / Build & push demo images (push) Failing after 2m9s

Replaces the external flasher.meshcore.co.uk link with a button that
opens the global device-setup modal directly at its flash step, via a
new manual entry point in the mesh store (flashFlowPath). Manual opens
target the connected radio (else the first detected stick), skip the
read-only probe — the port is held by the live session and a second tty
opener corrupts it; the backend flash job stops the listener itself —
and close the modal instead of stepping back to the detection screen.
Button is disabled with a hint when no radio is present.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-07-29 04:43:38 -04:00
co-authored by Claude Fable 5
parent c99f1c7b77
commit 6ba39041d0
4 changed files with 59 additions and 7 deletions
+18 -6
View File
@@ -21,6 +21,18 @@ const mesh = useMeshStore()
const transport = useTransportStore()
const route = useRoute()
// "Flash LoRa" header button target: the connected radio wins, else any
// detected-but-unconnected stick. Opens the global setup modal at its
// flash step (backend stops the listener and frees the port itself).
const flashLoraPath = computed(() =>
(mesh.status?.device_connected && mesh.status.device_path) ||
mesh.status?.detected_devices?.[0] ||
''
)
function openFlashLora() {
if (flashLoraPath.value) mesh.openFlashFlow(flashLoraPath.value)
}
// Responsive layout breakpoints
const isWideDesktop = ref(window.innerWidth >= 1536)
const isVeryWideDesktop = ref(window.innerWidth >= 2560 && window.innerHeight >= 1200)
@@ -1860,14 +1872,14 @@ async function downloadAttachment(payload: MeshAttachmentPayload) {
<span v-else-if="mesh.status?.device_present" class="mesh-subtitle-badge">Mesh device detected</span>
</p>
</div>
<a
href="https://flasher.meshcore.co.uk/"
target="_blank"
rel="noopener noreferrer"
<button
class="glass-button mesh-flasher-btn"
:disabled="!flashLoraPath"
:title="flashLoraPath ? '' : 'Plug in a LoRa radio first'"
@click="openFlashLora"
>
Flash Meshcore <span class="mesh-flasher-sep">|</span> Choose Companion USB
</a>
Flash LoRa
</button>
</div>
<!-- Error banner -->
+1
View File
@@ -28,6 +28,7 @@
.mesh-subtitle { color: rgba(255, 255, 255, 0.5); font-size: 0.85rem; margin: 2px 0 0; display: flex; align-items: center; gap: 8px; }
.mesh-subtitle-badge { font-size: 0.65rem; font-weight: 600; color: #4ade80; background: rgba(74, 222, 128, 0.12); padding: 1px 6px; border-radius: 4px; text-transform: uppercase; letter-spacing: 0.5px; }
.mesh-flasher-btn { display: inline-flex; align-items: center; gap: 0; padding: 8px 16px; font-size: 0.9rem; text-decoration: none; white-space: nowrap; flex-shrink: 0; }
.mesh-flasher-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.mesh-flasher-sep { margin: 0 8px; color: rgba(255, 255, 255, 0.2); }
.mesh-error { color: #ef4444; font-size: 0.85rem; padding: 8px 12px; background: rgba(239, 68, 68, 0.1); border-radius: 8px; border: 1px solid rgba(239, 68, 68, 0.2); flex-shrink: 0; }
.mesh-columns { display: flex; gap: 16px; flex: 1; min-height: 0; overflow: hidden; }