feat: wire model download UI and native docs

This commit is contained in:
Evandro committed 2026-06-11 01:18:40 -03:00
1 parent 0c39063150
commit 8f754b3f00
8 files changed
+218 -152

No files matched your search

+37 -2
View File
@@ -33,10 +33,12 @@ export interface ModelWithStatus {
filename: string;
quantization: string;
sizeBytes: number;
downloadUrl?: string;
languages: string[];
recommendedForSimplePc: boolean;
};
status: "notInstalled" | "ready" | { error: string };
localPath?: string | null;
}
export interface TranscriptDraft {
@@ -123,6 +125,12 @@ function formatBytes(bytes: number): string {
return `${mib.toFixed(0)} MiB`;
}
function modelStatusLabel(status: ModelWithStatus["status"]): string {
if (status === "ready") return "pronto";
if (status === "notInstalled") return "não instalado";
return status.error;
}
async function safeSnapshot(client: NativeClient): Promise<AppSnapshot> {
try {
return await client.invoke<AppSnapshot>("get_app_snapshot");
@@ -205,7 +213,13 @@ export function createTranscriptionApp(
const modelPanel = element("aside", "model-panel");
const modelTitle = element("h2", undefined, "Modelo offline");
const modelDetails = element("p");
modelPanel.append(modelTitle, modelDetails);
const modelStatus = element("p", "model-status");
const downloadModelButton = element(
"button",
"ghost-button",
"Baixar modelo",
) as HTMLButtonElement;
modelPanel.append(modelTitle, modelDetails, modelStatus, downloadModelButton);
shell.append(topbar, editorLabel, editor, message, actions, modelPanel);
mount.append(shell);
@@ -223,10 +237,17 @@ export function createTranscriptionApp(
? "Parar e transcrever"
: "Iniciar gravação";
const firstModel = snapshot.models[0]?.model;
const firstModelStatus = snapshot.models[0];
const firstModel = firstModelStatus?.model;
modelDetails.textContent = firstModel
? `${firstModel.displayName} · ${firstModel.quantization} · ${formatBytes(firstModel.sizeBytes)} · ${firstModel.repository}`
: "Nenhum modelo offline homologado encontrado.";
modelStatus.textContent = firstModelStatus
? `Status: ${modelStatusLabel(firstModelStatus.status)}`
: "Status: indisponível";
downloadModelButton.disabled = firstModelStatus?.status === "ready";
downloadModelButton.textContent =
firstModelStatus?.status === "ready" ? "Modelo pronto" : "Baixar modelo";
};
const refresh = async (): Promise<void> => {
@@ -249,6 +270,20 @@ export function createTranscriptionApp(
void toggleRecording().catch(showError);
});
downloadModelButton.addEventListener("click", () => {
downloadModelButton.disabled = true;
downloadModelButton.textContent = "Baixando...";
message.textContent = "Baixando modelo offline. Isso pode demorar.";
void client
.invoke("download_default_model_command")
.then(refresh)
.catch((error) => {
downloadModelButton.disabled = false;
downloadModelButton.textContent = "Baixar modelo";
showError(error);
});
});
continueButton.addEventListener("click", () => {
void client
.invoke<AppSnapshot>("start_recording")