feat(tray): add cancel recording/transcribing actions
This commit is contained in:
parent
e92f94573e
commit
6c26d6afb8
3 changed files with 108 additions and 0 deletions
|
|
@ -122,6 +122,25 @@ pub fn run() {
|
|||
"check_updates" => {
|
||||
let _ = app.emit("check-for-updates", ());
|
||||
}
|
||||
"cancel_listening" => {
|
||||
use crate::utils::{change_tray_icon, TrayIconState};
|
||||
use crate::managers::audio::AudioRecordingManager;
|
||||
use std::sync::Arc;
|
||||
|
||||
// Cancel the recording without transcribing
|
||||
let rm = app.state::<Arc<AudioRecordingManager>>();
|
||||
rm.cancel_recording();
|
||||
|
||||
// Return to idle state
|
||||
change_tray_icon(app, TrayIconState::Idle);
|
||||
}
|
||||
"cancel_transcribing" => {
|
||||
use crate::utils::{change_tray_icon, TrayIconState};
|
||||
|
||||
// For now, just return to idle state
|
||||
// TODO: In a future version, we could add actual request cancellation
|
||||
change_tray_icon(app, TrayIconState::Idle);
|
||||
}
|
||||
"quit" => {
|
||||
app.exit(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -258,4 +258,25 @@ impl AudioRecordingManager {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Cancel any ongoing recording without returning audio samples
|
||||
pub fn cancel_recording(&self) {
|
||||
let mut state = self.state.lock().unwrap();
|
||||
|
||||
if let RecordingState::Recording { .. } = *state {
|
||||
*state = RecordingState::Idle;
|
||||
drop(state);
|
||||
|
||||
if let Some(rec) = self.recorder.lock().unwrap().as_ref() {
|
||||
let _ = rec.stop(); // Discard the result
|
||||
}
|
||||
|
||||
*self.is_recording.lock().unwrap() = false;
|
||||
|
||||
// In on-demand mode turn the mic off again
|
||||
if matches!(*self.mode.lock().unwrap(), MicrophoneMode::OnDemand) {
|
||||
self.stop_microphone_stream();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use tauri::image::Image;
|
|||
use tauri::tray::TrayIcon;
|
||||
use tauri::AppHandle;
|
||||
use tauri::Manager;
|
||||
use tauri::menu::{Menu, MenuItem, PredefinedMenuItem};
|
||||
use tauri_plugin_clipboard_manager::ClipboardExt;
|
||||
|
||||
fn send_paste() -> Result<(), String> {
|
||||
|
|
@ -70,6 +71,7 @@ pub fn paste(text: String, app_handle: AppHandle) -> Result<(), String> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum TrayIconState {
|
||||
Idle,
|
||||
Recording,
|
||||
|
|
@ -93,6 +95,72 @@ pub fn change_tray_icon(app: &AppHandle, icon: TrayIconState) {
|
|||
)
|
||||
.expect("failed to set icon"),
|
||||
));
|
||||
|
||||
// Update menu based on state
|
||||
update_tray_menu(app, &icon);
|
||||
}
|
||||
|
||||
pub fn update_tray_menu(app: &AppHandle, state: &TrayIconState) {
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let version_label = format!("Handy v{}", version);
|
||||
|
||||
// Platform-specific accelerators
|
||||
#[cfg(target_os = "macos")]
|
||||
let settings_accelerator = Some("Cmd+,");
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let settings_accelerator = Some("Ctrl+,");
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let quit_accelerator = Some("Cmd+Q");
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let quit_accelerator = Some("Ctrl+Q");
|
||||
|
||||
let version_i = MenuItem::with_id(app, "version", &version_label, false, None::<&str>).expect("failed to create version item");
|
||||
let settings_i = MenuItem::with_id(app, "settings", "Settings...", true, settings_accelerator).expect("failed to create settings item");
|
||||
let check_updates_i = MenuItem::with_id(app, "check_updates", "Check for Updates...", true, None::<&str>).expect("failed to create check updates item");
|
||||
let quit_i = MenuItem::with_id(app, "quit", "Quit", true, quit_accelerator).expect("failed to create quit item");
|
||||
|
||||
let menu = match state {
|
||||
TrayIconState::Recording => {
|
||||
let cancel_i = MenuItem::with_id(app, "cancel_listening", "Cancel Listening", true, None::<&str>).expect("failed to create cancel listening item");
|
||||
Menu::with_items(app, &[
|
||||
&version_i,
|
||||
&PredefinedMenuItem::separator(app).expect("failed to create separator"),
|
||||
&cancel_i,
|
||||
&PredefinedMenuItem::separator(app).expect("failed to create separator"),
|
||||
&settings_i,
|
||||
&check_updates_i,
|
||||
&PredefinedMenuItem::separator(app).expect("failed to create separator"),
|
||||
&quit_i,
|
||||
]).expect("failed to create menu")
|
||||
}
|
||||
TrayIconState::Transcribing => {
|
||||
let cancel_i = MenuItem::with_id(app, "cancel_transcribing", "Cancel Transcribing", true, None::<&str>).expect("failed to create cancel transcribing item");
|
||||
Menu::with_items(app, &[
|
||||
&version_i,
|
||||
&PredefinedMenuItem::separator(app).expect("failed to create separator"),
|
||||
&cancel_i,
|
||||
&PredefinedMenuItem::separator(app).expect("failed to create separator"),
|
||||
&settings_i,
|
||||
&check_updates_i,
|
||||
&PredefinedMenuItem::separator(app).expect("failed to create separator"),
|
||||
&quit_i,
|
||||
]).expect("failed to create menu")
|
||||
}
|
||||
TrayIconState::Idle => {
|
||||
Menu::with_items(app, &[
|
||||
&version_i,
|
||||
&PredefinedMenuItem::separator(app).expect("failed to create separator"),
|
||||
&settings_i,
|
||||
&check_updates_i,
|
||||
&PredefinedMenuItem::separator(app).expect("failed to create separator"),
|
||||
&quit_i,
|
||||
]).expect("failed to create menu")
|
||||
}
|
||||
};
|
||||
|
||||
let tray = app.state::<TrayIcon>();
|
||||
let _ = tray.set_menu(Some(menu));
|
||||
}
|
||||
|
||||
/// Plays an audio resource from the resources directory.
|
||||
|
|
|
|||
Loading…
Reference in a new issue