cleanup some code + fix bug where shortcut would still be pressed making
the next transcript not go through
This commit is contained in:
parent
40b4917d75
commit
a91cfdb7e8
3 changed files with 113 additions and 103 deletions
|
|
@ -1,2 +1,10 @@
|
|||
pub mod audio;
|
||||
pub mod models;
|
||||
|
||||
use crate::utils::cancel_current_operation;
|
||||
use tauri::AppHandle;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn cancel_operation(app: AppHandle) {
|
||||
cancel_current_operation(&app);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use managers::transcription::TranscriptionManager;
|
|||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tauri::image::Image;
|
||||
use tauri::menu::{Menu, MenuItem, PredefinedMenuItem};
|
||||
|
||||
use tauri::tray::TrayIconBuilder;
|
||||
use tauri::Emitter;
|
||||
use tauri::{AppHandle, Manager};
|
||||
|
|
@ -52,48 +52,11 @@ pub fn run() {
|
|||
))
|
||||
.manage(Mutex::new(ShortcutToggleStates::default()))
|
||||
.setup(move |app| {
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let version_label = format!("Handy v{}", version);
|
||||
let version_i = MenuItem::with_id(app, "version", &version_label, false, None::<&str>)?;
|
||||
|
||||
// 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 settings_i =
|
||||
MenuItem::with_id(app, "settings", "Settings...", true, settings_accelerator)?;
|
||||
let check_updates_i = MenuItem::with_id(
|
||||
app,
|
||||
"check_updates",
|
||||
"Check for Updates...",
|
||||
true,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let quit_i = MenuItem::with_id(app, "quit", "Quit", true, quit_accelerator)?;
|
||||
let menu = Menu::with_items(
|
||||
app,
|
||||
&[
|
||||
&version_i,
|
||||
&PredefinedMenuItem::separator(app)?,
|
||||
&settings_i,
|
||||
&check_updates_i,
|
||||
&PredefinedMenuItem::separator(app)?,
|
||||
&quit_i,
|
||||
],
|
||||
)?;
|
||||
let tray = TrayIconBuilder::new()
|
||||
.icon(Image::from_path(app.path().resolve(
|
||||
"resources/tray_idle.png",
|
||||
tauri::path::BaseDirectory::Resource,
|
||||
)?)?)
|
||||
.menu(&menu)
|
||||
.show_menu_on_left_click(true)
|
||||
.on_menu_event(|app, event| match event.id.as_ref() {
|
||||
"settings" => {
|
||||
|
|
@ -122,24 +85,11 @@ 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);
|
||||
"cancel" => {
|
||||
use crate::utils::cancel_current_operation;
|
||||
|
||||
// Use centralized cancellation that handles all operations
|
||||
cancel_current_operation(app);
|
||||
}
|
||||
"quit" => {
|
||||
app.exit(0);
|
||||
|
|
@ -149,6 +99,9 @@ pub fn run() {
|
|||
.build(app)?;
|
||||
app.manage(tray);
|
||||
|
||||
// Initialize tray menu with idle state
|
||||
utils::update_tray_menu(&app.handle(), &utils::TrayIconState::Idle);
|
||||
|
||||
// Get the autostart manager
|
||||
let autostart_manager = app.autolaunch();
|
||||
// Enable autostart
|
||||
|
|
@ -196,6 +149,7 @@ pub fn run() {
|
|||
shortcut::change_audio_feedback_setting,
|
||||
shortcut::change_translate_to_english_setting,
|
||||
trigger_update_check,
|
||||
commands::cancel_operation,
|
||||
commands::models::get_available_models,
|
||||
commands::models::get_model_info,
|
||||
commands::models::download_model,
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ use std::fs::File;
|
|||
use std::io::BufReader;
|
||||
use std::thread;
|
||||
use tauri::image::Image;
|
||||
use tauri::menu::{Menu, MenuItem, PredefinedMenuItem};
|
||||
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> {
|
||||
|
|
@ -100,63 +100,111 @@ pub fn change_tray_icon(app: &AppHandle, icon: TrayIconState) {
|
|||
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);
|
||||
/// Centralized cancellation function that can be called from anywhere in the app.
|
||||
/// Handles cancelling both recording and transcription operations and updates UI state.
|
||||
pub fn cancel_current_operation(app: &AppHandle) {
|
||||
use crate::actions::ACTION_MAP;
|
||||
use crate::managers::audio::AudioRecordingManager;
|
||||
use crate::ManagedToggleState;
|
||||
use std::sync::Arc;
|
||||
|
||||
println!("Initiating operation cancellation...");
|
||||
|
||||
// First, reset all shortcut toggle states and call stop actions
|
||||
// This is critical for non-push-to-talk mode where shortcuts toggle on/off
|
||||
let toggle_state_manager = app.state::<ManagedToggleState>();
|
||||
if let Ok(mut states) = toggle_state_manager.lock() {
|
||||
// For each currently active toggle, call its stop action and reset state
|
||||
let active_bindings: Vec<String> = states
|
||||
.active_toggles
|
||||
.iter()
|
||||
.filter(|(_, &is_active)| is_active)
|
||||
.map(|(binding_id, _)| binding_id.clone())
|
||||
.collect();
|
||||
|
||||
for binding_id in active_bindings {
|
||||
println!("Stopping active action for binding: {}", binding_id);
|
||||
|
||||
// Call the action's stop method to ensure proper cleanup
|
||||
if let Some(action) = ACTION_MAP.get(&binding_id) {
|
||||
action.stop(app, &binding_id, "cancelled");
|
||||
}
|
||||
|
||||
// Reset the toggle state
|
||||
if let Some(is_active) = states.active_toggles.get_mut(&binding_id) {
|
||||
*is_active = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eprintln!("Warning: Failed to lock toggle state manager during cancellation");
|
||||
}
|
||||
|
||||
// Cancel any ongoing recording
|
||||
let audio_manager = app.state::<Arc<AudioRecordingManager>>();
|
||||
audio_manager.cancel_recording();
|
||||
|
||||
// Update tray icon and menu to idle state
|
||||
change_tray_icon(app, TrayIconState::Idle);
|
||||
|
||||
println!("Operation cancellation completed - returned to idle state");
|
||||
}
|
||||
|
||||
pub fn update_tray_menu(app: &AppHandle, state: &TrayIconState) {
|
||||
// Platform-specific accelerators
|
||||
#[cfg(target_os = "macos")]
|
||||
let settings_accelerator = Some("Cmd+,");
|
||||
let (settings_accelerator, quit_accelerator) = (Some("Cmd+,"), Some("Cmd+Q"));
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let settings_accelerator = Some("Ctrl+,");
|
||||
let (settings_accelerator, quit_accelerator) = (Some("Ctrl+,"), Some("Ctrl+Q"));
|
||||
|
||||
#[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");
|
||||
// Create common menu items
|
||||
let version_label = format!("Handy v{}", env!("CARGO_PKG_VERSION"));
|
||||
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 separator = || PredefinedMenuItem::separator(app).expect("failed to create separator");
|
||||
|
||||
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, &[
|
||||
TrayIconState::Recording | TrayIconState::Transcribing => {
|
||||
let cancel_i = MenuItem::with_id(app, "cancel", "Cancel", true, None::<&str>)
|
||||
.expect("failed to create cancel item");
|
||||
Menu::with_items(
|
||||
app,
|
||||
&[
|
||||
&version_i,
|
||||
&separator(),
|
||||
&cancel_i,
|
||||
&separator(),
|
||||
&settings_i,
|
||||
&check_updates_i,
|
||||
&separator(),
|
||||
&quit_i,
|
||||
],
|
||||
)
|
||||
.expect("failed to create menu")
|
||||
}
|
||||
TrayIconState::Idle => Menu::with_items(
|
||||
app,
|
||||
&[
|
||||
&version_i,
|
||||
&PredefinedMenuItem::separator(app).expect("failed to create separator"),
|
||||
&cancel_i,
|
||||
&PredefinedMenuItem::separator(app).expect("failed to create separator"),
|
||||
&separator(),
|
||||
&settings_i,
|
||||
&check_updates_i,
|
||||
&PredefinedMenuItem::separator(app).expect("failed to create separator"),
|
||||
&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")
|
||||
}
|
||||
],
|
||||
)
|
||||
.expect("failed to create menu"),
|
||||
};
|
||||
|
||||
let tray = app.state::<TrayIcon>();
|
||||
|
|
|
|||
Loading…
Reference in a new issue