mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-02-12 08:41:36 +00:00
Initial implementation of global shortcut
This commit is contained in:
parent
c9f037bb2c
commit
6ed9338d23
@ -1,5 +1,7 @@
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Tools;
|
||||
using AIStudio.Tools.MIME;
|
||||
using AIStudio.Tools.Rust;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@ -24,6 +26,9 @@ public partial class VoiceRecorder : MSGComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// Register for global shortcut events:
|
||||
this.ApplyFilters([], [Event.TAURI_EVENT_RECEIVED]);
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
try
|
||||
@ -37,6 +42,37 @@ public partial class VoiceRecorder : MSGComponentBase
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task ProcessIncomingMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
|
||||
{
|
||||
switch (triggeredEvent)
|
||||
{
|
||||
case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.GLOBAL_SHORTCUT_PRESSED } tauriEvent:
|
||||
// Check if this is the voice recording toggle shortcut:
|
||||
if (tauriEvent.Payload.Count > 0 && tauriEvent.Payload[0] == "voice_recording_toggle")
|
||||
{
|
||||
this.Logger.LogInformation("Global shortcut triggered for voice recording toggle.");
|
||||
await this.ToggleRecordingFromShortcut();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the recording state when triggered by a global shortcut.
|
||||
/// </summary>
|
||||
private async Task ToggleRecordingFromShortcut()
|
||||
{
|
||||
// Don't allow toggle if transcription is in progress or preparing:
|
||||
if (this.isTranscribing || this.isPreparing)
|
||||
{
|
||||
this.Logger.LogDebug("Ignoring shortcut: transcription or preparation is in progress.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle the recording state:
|
||||
await this.OnRecordingToggled(!this.isRecording);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private uint numReceivedChunks;
|
||||
|
||||
@ -15,4 +15,6 @@ public enum TauriEventType
|
||||
FILE_DROP_HOVERED,
|
||||
FILE_DROP_DROPPED,
|
||||
FILE_DROP_CANCELED,
|
||||
|
||||
GLOBAL_SHORTCUT_PRESSED,
|
||||
}
|
||||
@ -9,7 +9,7 @@ authors = ["Thorsten Sommer"]
|
||||
tauri-build = { version = "1.5", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "1.8", features = [ "http-all", "updater", "shell-sidecar", "shell-open", "dialog"] }
|
||||
tauri = { version = "1.8", features = [ "http-all", "updater", "shell-sidecar", "shell-open", "dialog", "global-shortcut"] }
|
||||
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_json = "1.0.140"
|
||||
|
||||
@ -8,7 +8,7 @@ use rocket::serde::json::Json;
|
||||
use rocket::serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
use tauri::updater::UpdateResponse;
|
||||
use tauri::{FileDropEvent, UpdaterEvent, RunEvent, Manager, PathResolver, Window, WindowEvent};
|
||||
use tauri::{FileDropEvent, GlobalShortcutManager, UpdaterEvent, RunEvent, Manager, PathResolver, Window, WindowEvent};
|
||||
use tauri::api::dialog::blocking::FileDialogBuilder;
|
||||
use tokio::sync::broadcast;
|
||||
use tokio::time;
|
||||
@ -65,6 +65,9 @@ pub fn start_tauri() {
|
||||
// Get the main window:
|
||||
let window = app.get_window("main").expect("Failed to get main window.");
|
||||
|
||||
// Clone the event sender for the global shortcut handler before moving it into the window event closure:
|
||||
let shortcut_event_sender = event_sender.clone();
|
||||
|
||||
// Register a callback for window events, such as file drops. We have to use
|
||||
// this handler in addition to the app event handler, because file drop events
|
||||
// are only available in the window event handler (is a bug, cf. https://github.com/tauri-apps/tauri/issues/14338):
|
||||
@ -83,6 +86,24 @@ pub fn start_tauri() {
|
||||
// Save the main window for later access:
|
||||
*MAIN_WINDOW.lock().unwrap() = Some(window);
|
||||
|
||||
// Register global shortcuts for voice recording toggle.
|
||||
// CmdOrControl+1 will be Cmd+1 on macOS and Ctrl+1 on Windows/Linux:
|
||||
let mut shortcut_manager = app.global_shortcut_manager();
|
||||
match shortcut_manager.register("CmdOrControl+1", move || {
|
||||
info!(Source = "Tauri"; "Global shortcut CmdOrControl+1 triggered for voice recording toggle.");
|
||||
let event = Event::new(TauriEventType::GlobalShortcutPressed, vec!["voice_recording_toggle".to_string()]);
|
||||
let sender = shortcut_event_sender.clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
match sender.send(event) {
|
||||
Ok(_) => {},
|
||||
Err(error) => error!(Source = "Tauri"; "Failed to send global shortcut event: {error}"),
|
||||
}
|
||||
});
|
||||
}) {
|
||||
Ok(_) => info!(Source = "Bootloader Tauri"; "Global shortcut CmdOrControl+1 registered successfully."),
|
||||
Err(error) => error!(Source = "Bootloader Tauri"; "Failed to register global shortcut: {error}"),
|
||||
}
|
||||
|
||||
info!(Source = "Bootloader Tauri"; "Setup is running.");
|
||||
let data_path = app.path_resolver().app_local_data_dir().unwrap();
|
||||
let data_path = data_path.join("data");
|
||||
@ -323,6 +344,8 @@ pub enum TauriEventType {
|
||||
FileDropHovered,
|
||||
FileDropDropped,
|
||||
FileDropCanceled,
|
||||
|
||||
GlobalShortcutPressed,
|
||||
}
|
||||
|
||||
/// Changes the location of the main window to the given URL.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user