Add a global ToggleDictation keybinding
This commit is contained in:
@@ -1,21 +1,27 @@
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use std::time::Duration;
|
||||
|
||||
use chat_ui::ToggleDictation;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use gpui::PathPromptOptions;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use gpui::Task;
|
||||
use gpui::http_client::Url;
|
||||
use gpui::{
|
||||
AnyElement, App, AppContext, Context, Entity, IntoElement, ParentElement, Render, Styled,
|
||||
Subscription, Task, Window, div,
|
||||
Subscription, Window, div,
|
||||
};
|
||||
use gpui_kit::assets::IconName;
|
||||
use gpui_kit::component::button::{Button, ButtonVariants};
|
||||
use gpui_kit::component::input::{Input, InputEvent, InputState, NumberInput};
|
||||
use gpui_kit::component::kbd::Kbd;
|
||||
use gpui_kit::component::menu::{DropdownMenu, PopupMenuItem};
|
||||
use gpui_kit::component::notification::Notification;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use gpui_kit::component::progress::Progress;
|
||||
use gpui_kit::component::separator::Separator;
|
||||
use gpui_kit::component::switch::Switch;
|
||||
use gpui_kit::component::{ActiveTheme, Disableable, Sizable, WindowExt, h_flex, v_flex};
|
||||
use gpui_kit::component::{Disableable, Sizable, WindowExt, h_flex, v_flex};
|
||||
use settings::{AppSettings, AppearanceMode};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use speech::model::{self as speech_model};
|
||||
@@ -236,66 +242,90 @@ impl Preferences {
|
||||
|
||||
#[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 size = speech_model::total_size() / 1_000_000;
|
||||
let status = speech_model::status();
|
||||
|
||||
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();
|
||||
}),
|
||||
let (description, control) = match &status {
|
||||
speech_model::Status::NotInstalled => (
|
||||
format!("{size} MB download"),
|
||||
Button::new("download-model")
|
||||
.label("Download")
|
||||
.secondary()
|
||||
.small()
|
||||
.on_click(|_, _window, cx| {
|
||||
speech_model::start_download();
|
||||
cx.refresh_windows();
|
||||
})
|
||||
.into_any_element(),
|
||||
),
|
||||
speech_model::Status::Downloading { downloaded, total } => (
|
||||
format!(
|
||||
"Downloading · {} of {} MB",
|
||||
downloaded / 1_000_000,
|
||||
total / 1_000_000
|
||||
),
|
||||
Button::new("cancel-download")
|
||||
.label("Cancel")
|
||||
.ghost()
|
||||
.small()
|
||||
.on_click(|_, _window, cx| {
|
||||
speech_model::cancel_download();
|
||||
cx.refresh_windows();
|
||||
})
|
||||
.into_any_element(),
|
||||
),
|
||||
speech_model::Status::Installed => (
|
||||
format!("Parakeet v3 · {size} MB"),
|
||||
Button::new("remove-model")
|
||||
.label("Remove")
|
||||
.secondary()
|
||||
.small()
|
||||
.on_click(|_, _window, cx| {
|
||||
speech_model::delete();
|
||||
cx.refresh_windows();
|
||||
})
|
||||
.into_any_element(),
|
||||
),
|
||||
};
|
||||
|
||||
settings_block("Speech Recognition", SPEECH, control, cx).into_any_element()
|
||||
let mut block = v_flex().w_full().gap_3().child(settings_row(
|
||||
"Speech model",
|
||||
description,
|
||||
control,
|
||||
cx,
|
||||
));
|
||||
|
||||
if let speech_model::Status::Downloading { downloaded, total } = &status {
|
||||
let (downloaded, total) = (*downloaded, *total);
|
||||
|
||||
block = block.child(
|
||||
Progress::new("speech-model-download")
|
||||
.value(downloaded as f32 / total.max(1) as f32 * 100.)
|
||||
.small(),
|
||||
);
|
||||
}
|
||||
|
||||
block.into_any_element()
|
||||
}
|
||||
}
|
||||
|
||||
/// Shows the keystroke actually bound to the dictation action at startup
|
||||
fn render_dictation_shortcut(
|
||||
&self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> impl IntoElement {
|
||||
let control = match Kbd::global_binding_for_action(&ToggleDictation, window) {
|
||||
Some(kbd) => kbd.into_any_element(),
|
||||
None => div().into_any_element(),
|
||||
};
|
||||
|
||||
settings_row("Shortcut", "Press to start or stop dictation", control, cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for Preferences {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
const SCREENING: &str = "Show an screening dialog to verify the unknown sender.";
|
||||
const WOT: &str = "Treat people followed by your contacts as known senders.";
|
||||
const AVATAR: &str = "Hide all avatar pictures to improve performance.";
|
||||
@@ -478,6 +508,9 @@ impl Render for Preferences {
|
||||
cx,
|
||||
))
|
||||
.child(Separator::horizontal())
|
||||
.child(self.render_speech(cx))
|
||||
.child(self.render_dictation_shortcut(window, cx))
|
||||
.child(Separator::horizontal())
|
||||
.child(settings_block(
|
||||
"Media Upload Service",
|
||||
MEDIA,
|
||||
@@ -495,6 +528,5 @@ impl Render for Preferences {
|
||||
),
|
||||
cx,
|
||||
))
|
||||
.child(self.render_speech(cx))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user