feat(ui): NPU detection + download indicator in Settings hardware (T3.4)

This commit is contained in:
iamdoubz committed 2026-07-02 17:16:51 -05:00
1 parent b23b00490a
commit 60fed63bc3
1 file changed
+85
+85
View File
@@ -7,6 +7,7 @@
import { calendar } from "../stores/calendar.svelte";
import ConsentNotice from "../components/ConsentNotice.svelte";
import { open } from "@tauri-apps/plugin-dialog";
import { api, events } from "../api";
import type { BackendId, SyncKind, SyncTargetConfig } from "../api";
import { trapFocus } from "../actions/trapFocus";
import {
@@ -62,9 +63,35 @@
let showConsent = $state(false);
let testResult = $state<{ ok: boolean; message: string } | null>(null);
// ---- NPU package download (T3.4) ----
let npuBusy = $state(false);
let npuMsg = $state<string | null>(null);
async function downloadNpuPackage() {
npuBusy = true;
npuMsg = "Starting…";
try {
await api.downloadNpuPackage();
await settings.loadHardware();
npuMsg = "NPU package ready.";
} catch (e) {
npuMsg = `Failed: ${e}`;
} finally {
npuBusy = false;
}
}
onMount(() => {
settings.load();
calendar.load();
const un = events.onNpuDownload((p) => {
if (p.stage === "model")
npuMsg = p.total ? `Model ${Math.round((100 * (p.received ?? 0)) / p.total)}%` : "Model…";
else if (p.stage === "runtime") npuMsg = `Runtime (${p.copied ?? 0} files)…`;
else if (p.stage === "done") npuMsg = p.ready ? "NPU package ready." : "Model ready.";
});
return () => {
void un.then((f) => f());
};
});
// ---- Recording ----
@@ -234,6 +261,36 @@
Falls back automatically (NPU → NVIDIA → AMD → Intel → CPU) if the chosen backend fails
to load.
</p>
{#if settings.hardware.npu?.present}
{@const npu = settings.hardware.npu}
{@const ready = npu.runtimeReady && npu.modelInstalled}
<div class="npu-package">
<div class="row">
<Cpu size={14} aria-hidden="true" />
<strong>NPU accelerator detected</strong>
{#if ready}
<span class="badge ok"><Check size={12} aria-hidden="true" /> Ready</span>
{:else if npuBusy}
<span class="badge busy">Downloading…</span>
{:else}
<span class="badge">Package needed</span>
{/if}
</div>
{#if !ready}
<p class="muted">
Your NPU needs a one-time acceleration package (Whisper ONNX model{npu.runtimeReady
? ""
: " + OpenVINO runtime"}). It downloads in the background; you can also start it
now.
</p>
<button onclick={downloadNpuPackage} disabled={npuBusy}>
{npuBusy ? "Downloading…" : "Download NPU package"}
</button>
{/if}
{#if npuMsg}<p class="muted npu-status">{npuMsg}</p>{/if}
</div>
{/if}
{:else}
<p class="muted">Hardware detection unavailable.</p>
{/if}
@@ -805,6 +862,34 @@
.badge.third {
color: var(--danger);
}
.badge.ok {
color: var(--success, #16a34a);
border-color: currentColor;
display: inline-flex;
align-items: center;
gap: 0.2rem;
}
.badge.busy {
color: var(--accent, #2563eb);
border-color: currentColor;
}
.npu-package {
margin-top: 0.6rem;
padding: 0.6rem 0.75rem;
border: 1px solid var(--border);
border-radius: 8px;
display: flex;
flex-direction: column;
gap: 0.4rem;
}
.npu-package .row {
display: flex;
align-items: center;
gap: 0.4rem;
}
.npu-status {
font-variant-numeric: tabular-nums;
}
.host {
font-size: 0.75rem;
color: var(--muted);