192 lines
6.5 KiB
Rust
192 lines
6.5 KiB
Rust
use serde::Serialize;
|
|
use tauri::{App, AppHandle, Manager};
|
|
use tauri_plugin_global_shortcut::GlobalShortcutExt;
|
|
use tauri_plugin_global_shortcut::{Shortcut, ShortcutState};
|
|
|
|
use crate::actions::ACTION_MAP;
|
|
use crate::settings::ShortcutBinding;
|
|
use crate::settings::{self, get_settings};
|
|
use crate::ManagedToggleState;
|
|
|
|
pub fn init_shortcuts(app: &App) {
|
|
let settings = settings::load_or_create_app_settings(app);
|
|
|
|
// Register shortcuts with the bindings from settings
|
|
for (_id, binding) in settings.bindings {
|
|
// Pass app.handle() which is &AppHandle
|
|
if let Err(e) = _register_shortcut(app.handle(), binding) {
|
|
eprintln!("Failed to register shortcut {}: {}", _id, e);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
pub struct BindingResponse {
|
|
success: bool,
|
|
binding: Option<ShortcutBinding>,
|
|
error: Option<String>,
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn change_binding(
|
|
app: AppHandle,
|
|
id: String,
|
|
binding: String,
|
|
) -> Result<BindingResponse, String> {
|
|
let mut settings = settings::get_settings(&app);
|
|
|
|
// Get the binding to modify
|
|
let binding_to_modify = match settings.bindings.get(&id) {
|
|
Some(binding) => binding.clone(),
|
|
None => {
|
|
return Ok(BindingResponse {
|
|
success: false,
|
|
binding: None,
|
|
error: Some(format!("Binding with id '{}' not found", id)),
|
|
})
|
|
}
|
|
};
|
|
|
|
// Unregister the existing binding
|
|
if let Err(e) = _unregister_shortcut(&app, binding_to_modify.clone()) {
|
|
return Ok(BindingResponse {
|
|
success: false,
|
|
binding: None,
|
|
error: Some(format!("Failed to unregister shortcut: {}", e)),
|
|
});
|
|
}
|
|
|
|
// Create an updated binding
|
|
let mut updated_binding = binding_to_modify;
|
|
updated_binding.current_binding = binding;
|
|
|
|
// Register the new binding
|
|
if let Err(e) = _register_shortcut(&app, updated_binding.clone()) {
|
|
return Ok(BindingResponse {
|
|
success: false,
|
|
binding: None,
|
|
error: Some(format!("Failed to register shortcut: {}", e)),
|
|
});
|
|
}
|
|
|
|
// Update the binding in the settings
|
|
settings.bindings.insert(id, updated_binding.clone());
|
|
|
|
// Save the settings
|
|
settings::write_settings(&app, settings);
|
|
|
|
// Return the updated binding
|
|
Ok(BindingResponse {
|
|
success: true,
|
|
binding: Some(updated_binding),
|
|
error: None,
|
|
})
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn reset_binding(app: AppHandle, id: String) -> Result<BindingResponse, String> {
|
|
let binding = settings::get_stored_binding(&app, &id);
|
|
|
|
return change_binding(app, id, binding.default_binding);
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn change_ptt_setting(app: AppHandle, enabled: bool) -> Result<(), String> {
|
|
let mut settings = settings::get_settings(&app);
|
|
|
|
// TODO if the setting is currently false, we probably want to
|
|
// cancel any ongoing recordings or actions
|
|
settings.push_to_talk = enabled;
|
|
|
|
settings::write_settings(&app, settings);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn change_audio_feedback_setting(app: AppHandle, enabled: bool) -> Result<(), String> {
|
|
let mut settings = settings::get_settings(&app);
|
|
settings.audio_feedback = enabled;
|
|
settings::write_settings(&app, settings);
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub fn change_translate_to_english_setting(app: AppHandle, enabled: bool) -> Result<(), String> {
|
|
let mut settings = settings::get_settings(&app);
|
|
settings.translate_to_english = enabled;
|
|
settings::write_settings(&app, settings);
|
|
Ok(())
|
|
}
|
|
|
|
fn _register_shortcut(app: &AppHandle, binding: ShortcutBinding) -> Result<(), String> {
|
|
// Parse shortcut and return error if it fails
|
|
let shortcut = match binding.current_binding.parse::<Shortcut>() {
|
|
Ok(s) => s,
|
|
Err(e) => return Err(format!("Failed to parse shortcut: {}", e)),
|
|
};
|
|
|
|
// Clone binding.id for use in the closure
|
|
let binding_id_for_closure = binding.id.clone();
|
|
|
|
app.global_shortcut()
|
|
.on_shortcut(shortcut, move |ah, scut, event| {
|
|
if scut == &shortcut {
|
|
let shortcut_string = scut.into_string();
|
|
let settings = get_settings(ah);
|
|
|
|
if let Some(action) = ACTION_MAP.get(&binding_id_for_closure) {
|
|
if settings.push_to_talk {
|
|
if event.state == ShortcutState::Pressed {
|
|
action.start(ah, &binding_id_for_closure, &shortcut_string);
|
|
} else if event.state == ShortcutState::Released {
|
|
action.stop(ah, &binding_id_for_closure, &shortcut_string);
|
|
}
|
|
} else {
|
|
if event.state == ShortcutState::Pressed {
|
|
let toggle_state_manager = ah.state::<ManagedToggleState>();
|
|
|
|
let mut states = toggle_state_manager.lock().expect("Failed to lock toggle state manager");
|
|
|
|
let is_currently_active = states.active_toggles
|
|
.entry(binding_id_for_closure.clone())
|
|
.or_insert(false);
|
|
|
|
if *is_currently_active {
|
|
action.stop(
|
|
ah,
|
|
&binding_id_for_closure,
|
|
&shortcut_string,
|
|
);
|
|
*is_currently_active = false; // Update state to inactive
|
|
} else {
|
|
action.start(ah, &binding_id_for_closure, &shortcut_string);
|
|
*is_currently_active = true; // Update state to active
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
println!(
|
|
"Warning: No action defined in ACTION_MAP for shortcut ID '{}'. Shortcut: '{}', State: {:?}",
|
|
binding_id_for_closure, shortcut_string, event.state
|
|
);
|
|
}
|
|
}
|
|
})
|
|
.map_err(|e| format!("Couldn't register shortcut: {}", e))?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn _unregister_shortcut(app: &AppHandle, binding: ShortcutBinding) -> Result<(), String> {
|
|
let shortcut = match binding.current_binding.parse::<Shortcut>() {
|
|
Ok(s) => s,
|
|
Err(e) => return Err(format!("Failed to parse shortcut: {}", e)),
|
|
};
|
|
|
|
app.global_shortcut()
|
|
.unregister(shortcut)
|
|
.map_err(|e| format!("Failed to unregister shortcut: {}", e))?;
|
|
|
|
Ok(())
|
|
}
|