add parakeet

This commit is contained in:
2026-10-27 10:55:05 +07:00
parent 9fa4f4f2ff
commit 589c43b982
13 changed files with 1527 additions and 21 deletions
+1
View File
@@ -15,6 +15,7 @@ chat_ui = { path = "../chat_ui" }
nip29 = { path = "../nip29" }
nip29_ui = { path = "../nip29_ui" }
settings = { path = "../settings" }
speech = { path = "../speech" }
person = { path = "../person" }
auto_update = { path = "../auto_update" }
+108 -3
View File
@@ -1,9 +1,12 @@
#[cfg(not(target_arch = "wasm32"))]
use std::time::Duration;
#[cfg(not(target_arch = "wasm32"))]
use gpui::PathPromptOptions;
use gpui::http_client::Url;
use gpui::{
App, AppContext, Context, Entity, IntoElement, ParentElement, Render, Styled, Subscription,
Window, div,
AnyElement, App, AppContext, Context, Entity, IntoElement, ParentElement, Render, Styled,
Subscription, Task, Window, div,
};
use gpui_kit::assets::IconName;
use gpui_kit::component::button::{Button, ButtonVariants};
@@ -12,8 +15,10 @@ use gpui_kit::component::menu::{DropdownMenu, PopupMenuItem};
use gpui_kit::component::notification::Notification;
use gpui_kit::component::separator::Separator;
use gpui_kit::component::switch::Switch;
use gpui_kit::component::{Disableable, Sizable, WindowExt, h_flex, v_flex};
use gpui_kit::component::{ActiveTheme, Disableable, Sizable, WindowExt, h_flex, v_flex};
use settings::{AppSettings, AppearanceMode};
#[cfg(not(target_arch = "wasm32"))]
use speech::model::{self as speech_model};
use ui::{settings_block, settings_row};
/// Bounds for the theme number inputs
@@ -29,6 +34,8 @@ pub struct Preferences {
font_size_input: Entity<InputState>,
radius_input: Entity<InputState>,
radius_lg_input: Entity<InputState>,
#[cfg(not(target_arch = "wasm32"))]
_speech_poll: Task<()>,
/// Keeps the control subscriptions alive while the dialog is open
_subscriptions: Vec<Subscription>,
}
@@ -94,11 +101,40 @@ impl Preferences {
}),
];
#[cfg(not(target_arch = "wasm32"))]
let _speech_poll = cx.spawn_in(window, async move |this, cx| {
let timer = Duration::from_millis(500);
let mut last = speech_model::status();
loop {
cx.background_executor().timer(timer).await;
let status = speech_model::status();
let error = speech_model::take_error();
if status == last {
continue;
}
last = status;
this.update_in(cx, |_, window, cx| {
if let Some(error) = error {
window.push_notification(Notification::error(error).autohide(false), cx);
}
cx.notify();
})
.ok();
}
});
Self {
file_input,
font_size_input,
radius_input,
radius_lg_input,
#[cfg(not(target_arch = "wasm32"))]
_speech_poll,
_subscriptions: subscriptions,
}
}
@@ -188,6 +224,74 @@ impl Preferences {
.detach();
}
}
fn render_speech(
&mut self,
#[cfg_attr(target_arch = "wasm32", allow(unused_variables))] cx: &mut Context<Self>,
) -> AnyElement {
#[cfg(target_arch = "wasm32")]
{
return div().into_any_element();
}
#[cfg(not(target_arch = "wasm32"))]
{
const SPEECH: &str = "On-device speech model used by the speech to text feature. Audio never leaves the device.";
let control = match speech_model::status() {
speech_model::Status::NotInstalled => {
let size = speech_model::total_size() / 1024 / 1024;
h_flex().gap_1().child(
Button::new("download-model")
.label(format!("Download model ({size} MB)"))
.small()
.on_click(|_, _window, cx| {
speech_model::start_download();
cx.refresh_windows();
}),
)
}
speech_model::Status::Downloading { downloaded, total } => {
let percent = downloaded * 100 / total.max(1);
let downloaded = downloaded / 1024 / 1024;
let total = total / 1024 / 1024;
h_flex()
.gap_2()
.child(
div()
.text_sm()
.text_color(cx.theme().muted_foreground)
.child(format!("Downloading {percent}% · {downloaded}/{total} MB")),
)
.child(
Button::new("cancel-download")
.label("Cancel")
.small()
.on_click(|_, _window, cx| {
speech_model::cancel_download();
cx.refresh_windows();
}),
)
}
speech_model::Status::Installed => h_flex()
.gap_2()
.child(div().text_sm().child("Installed"))
.child(
Button::new("delete-model")
.label("Delete")
.small()
.on_click(|_, _window, cx| {
speech_model::delete();
cx.refresh_windows();
}),
),
};
settings_block("Speech Recognition", SPEECH, control, cx).into_any_element()
}
}
}
impl Render for Preferences {
@@ -391,5 +495,6 @@ impl Render for Preferences {
),
cx,
))
.child(self.render_speech(cx))
}
}