mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-02-12 06:41:37 +00:00
Made the shortcuts type-safe
This commit is contained in:
parent
9f3ade916d
commit
b2882e0d93
@ -1,4 +1,5 @@
|
||||
using AIStudio.Dialogs;
|
||||
using AIStudio.Tools.Rust;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@ -33,7 +34,7 @@ public partial class ConfigurationShortcut : ConfigurationBaseCore
|
||||
/// The name/identifier of the shortcut (used for conflict detection and registration).
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string ShortcutName { get; set; } = string.Empty;
|
||||
public Shortcut ShortcutId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The icon to display.
|
||||
@ -80,7 +81,7 @@ public partial class ConfigurationShortcut : ConfigurationBaseCore
|
||||
var dialogParameters = new DialogParameters<ShortcutDialog>
|
||||
{
|
||||
{ x => x.InitialShortcut, this.Shortcut() },
|
||||
{ x => x.ShortcutName, this.ShortcutName },
|
||||
{ x => x.ShortcutId, this.ShortcutId },
|
||||
};
|
||||
|
||||
var dialogReference = await this.DialogService.ShowAsync<ShortcutDialog>(
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
@using AIStudio.Settings
|
||||
@using AIStudio.Settings.DataModel
|
||||
@using AIStudio.Tools.Rust
|
||||
@inherits SettingsPanelBase
|
||||
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Apps" HeaderText="@T("App Options")">
|
||||
@ -33,6 +34,6 @@
|
||||
@if (PreviewFeatures.PRE_SPEECH_TO_TEXT_2026.IsEnabled(this.SettingsManager))
|
||||
{
|
||||
<ConfigurationSelect OptionDescription="@T("Select a transcription provider")" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.UseTranscriptionProvider)" Data="@this.GetFilteredTranscriptionProviders()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.UseTranscriptionProvider = selectedValue)" OptionHelp="@T("Select a transcription provider for transcribing your voice. Without a selected provider, dictation and transcription features will be disabled.")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.UseTranscriptionProvider, out var meta) && meta.IsLocked"/>
|
||||
<ConfigurationShortcut OptionDescription="@T("Voice recording shortcut")" Shortcut="@(() => this.SettingsManager.ConfigurationData.App.ShortcutVoiceRecording)" ShortcutUpdate="@(shortcut => this.SettingsManager.ConfigurationData.App.ShortcutVoiceRecording = shortcut)" ShortcutName="voice_recording_toggle" OptionHelp="@T("The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused.")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.ShortcutVoiceRecording, out var meta) && meta.IsLocked"/>
|
||||
<ConfigurationShortcut ShortcutId="Shortcut.VOICE_RECORDING_TOGGLE" OptionDescription="@T("Voice recording shortcut")" Shortcut="@(() => this.SettingsManager.ConfigurationData.App.ShortcutVoiceRecording)" ShortcutUpdate="@(shortcut => this.SettingsManager.ConfigurationData.App.ShortcutVoiceRecording = shortcut)" OptionHelp="@T("The global keyboard shortcut for toggling voice recording. This shortcut works system-wide, even when the app is not focused.")" IsLocked="() => ManagedConfiguration.TryGet(x => x.App, x => x.ShortcutVoiceRecording, out var meta) && meta.IsLocked"/>
|
||||
}
|
||||
</ExpansionPanel>
|
||||
@ -47,11 +47,12 @@ public partial class VoiceRecorder : MSGComponentBase
|
||||
{
|
||||
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")
|
||||
if (tauriEvent.TryGetShortcut(out var shortcutId) && shortcutId == Shortcut.VOICE_RECORDING_TOGGLE)
|
||||
{
|
||||
this.Logger.LogInformation("Global shortcut triggered for voice recording toggle.");
|
||||
await this.ToggleRecordingFromShortcut();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using AIStudio.Components;
|
||||
using AIStudio.Tools.Rust;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@ -24,10 +25,10 @@ public partial class ShortcutDialog : MSGComponentBase
|
||||
public string InitialShortcut { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The name/identifier of the shortcut for conflict detection.
|
||||
/// The identifier of the shortcut for conflict detection.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string ShortcutName { get; set; } = string.Empty;
|
||||
public Shortcut ShortcutId { get; set; }
|
||||
|
||||
private static readonly Dictionary<string, object?> USER_INPUT_ATTRIBUTES = new();
|
||||
|
||||
|
||||
17
app/MindWork AI Studio/Tools/Rust/Shortcut.cs
Normal file
17
app/MindWork AI Studio/Tools/Rust/Shortcut.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>
|
||||
/// Identifies a global keyboard shortcut.
|
||||
/// </summary>
|
||||
public enum Shortcut
|
||||
{
|
||||
/// <summary>
|
||||
/// Null pattern - no shortcut assigned or unknown shortcut.
|
||||
/// </summary>
|
||||
NONE = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Toggles voice recording on/off.
|
||||
/// </summary>
|
||||
VOICE_RECORDING_TOGGLE,
|
||||
}
|
||||
@ -5,4 +5,38 @@ namespace AIStudio.Tools.Rust;
|
||||
/// </summary>
|
||||
/// <param name="EventType">The type of the Tauri event.</param>
|
||||
/// <param name="Payload">The payload of the Tauri event.</param>
|
||||
public readonly record struct TauriEvent(TauriEventType EventType, List<string> Payload);
|
||||
public readonly record struct TauriEvent(TauriEventType EventType, List<string> Payload)
|
||||
{
|
||||
/// <summary>
|
||||
/// Attempts to parse the first payload element as a shortcut.
|
||||
/// </summary>
|
||||
/// <param name="shortcut">The parsed shortcut name if successful.</param>
|
||||
/// <returns>True if parsing was successful, false otherwise.</returns>
|
||||
public bool TryGetShortcut(out Shortcut shortcut)
|
||||
{
|
||||
shortcut = default;
|
||||
if (this.Payload.Count == 0)
|
||||
return false;
|
||||
|
||||
// Try standard enum parsing (handles PascalCase and numeric values):
|
||||
if (Enum.TryParse(this.Payload[0], ignoreCase: true, out shortcut))
|
||||
return true;
|
||||
|
||||
// Try parsing snake_case format (e.g., "voice_recording_toggle"):
|
||||
return TryParseSnakeCase(this.Payload[0], out shortcut);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to parse a snake_case string into a ShortcutName enum value.
|
||||
/// </summary>
|
||||
private static bool TryParseSnakeCase(string value, out Shortcut shortcut)
|
||||
{
|
||||
shortcut = default;
|
||||
|
||||
// Convert snake_case to UPPER_SNAKE_CASE for enum matching:
|
||||
var upperSnakeCase = value.ToUpperInvariant();
|
||||
|
||||
// Try to match against enum names (which are in UPPER_SNAKE_CASE):
|
||||
return Enum.TryParse(upperSnakeCase, ignoreCase: false, out shortcut);
|
||||
}
|
||||
};
|
||||
@ -1,5 +1,6 @@
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools.Rust;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
@ -57,44 +58,51 @@ public sealed class GlobalShortcutService : BackgroundService, IMessageBusReceiv
|
||||
}
|
||||
}
|
||||
|
||||
public Task<TResult?> ProcessMessageWithResult<TPayload, TResult>(
|
||||
ComponentBase? sendingComponent, Event triggeredEvent, TPayload? data)
|
||||
=> Task.FromResult<TResult?>(default);
|
||||
public Task<TResult?> ProcessMessageWithResult<TPayload, TResult>(ComponentBase? sendingComponent, Event triggeredEvent, TPayload? data) => Task.FromResult<TResult?>(default);
|
||||
|
||||
#endregion
|
||||
|
||||
private async Task RegisterAllShortcuts()
|
||||
{
|
||||
this.logger.LogInformation("Registering global shortcuts.");
|
||||
|
||||
//
|
||||
// Voice recording shortcut (preview feature)
|
||||
//
|
||||
if (PreviewFeatures.PRE_SPEECH_TO_TEXT_2026.IsEnabled(this.settingsManager))
|
||||
foreach (var shortcutId in Enum.GetValues<Shortcut>())
|
||||
{
|
||||
var shortcut = this.settingsManager.ConfigurationData.App.ShortcutVoiceRecording;
|
||||
if (!string.IsNullOrWhiteSpace(shortcut))
|
||||
var shortcut = this.GetShortcutValue(shortcutId);
|
||||
var isEnabled = this.IsShortcutAllowed(shortcutId);
|
||||
|
||||
if (isEnabled && !string.IsNullOrWhiteSpace(shortcut))
|
||||
{
|
||||
var success = await this.rustService.UpdateGlobalShortcut("voice_recording_toggle", shortcut);
|
||||
var success = await this.rustService.UpdateGlobalShortcut(shortcutId, shortcut);
|
||||
if (success)
|
||||
this.logger.LogInformation("Global shortcut 'voice_recording_toggle' ({Shortcut}) registered.", shortcut);
|
||||
this.logger.LogInformation("Global shortcut '{ShortcutId}' ({Shortcut}) registered.", shortcutId, shortcut);
|
||||
else
|
||||
this.logger.LogWarning("Failed to register global shortcut 'voice_recording_toggle' ({Shortcut}).", shortcut);
|
||||
this.logger.LogWarning("Failed to register global shortcut '{ShortcutId}' ({Shortcut}).", shortcutId, shortcut);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable shortcut when empty
|
||||
await this.rustService.UpdateGlobalShortcut("voice_recording_toggle", string.Empty);
|
||||
// Disable the shortcut when empty or feature is disabled:
|
||||
await this.rustService.UpdateGlobalShortcut(shortcutId, string.Empty);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable the shortcut when the preview feature is disabled:
|
||||
await this.rustService.UpdateGlobalShortcut("voice_recording_toggle", string.Empty);
|
||||
}
|
||||
|
||||
|
||||
this.logger.LogInformation("Global shortcuts registration completed.");
|
||||
}
|
||||
|
||||
private string GetShortcutValue(Shortcut name) => name switch
|
||||
{
|
||||
Shortcut.VOICE_RECORDING_TOGGLE => this.settingsManager.ConfigurationData.App.ShortcutVoiceRecording,
|
||||
|
||||
_ => string.Empty,
|
||||
};
|
||||
|
||||
private bool IsShortcutAllowed(Shortcut name) => name switch
|
||||
{
|
||||
// Voice recording is a preview feature:
|
||||
Shortcut.VOICE_RECORDING_TOGGLE => PreviewFeatures.PRE_SPEECH_TO_TEXT_2026.IsEnabled(this.settingsManager),
|
||||
|
||||
// Other shortcuts are always allowed:
|
||||
_ => true,
|
||||
};
|
||||
|
||||
public static void Initialize() => IS_INITIALIZED = true;
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
// ReSharper disable NotAccessedPositionalProperty.Local
|
||||
using AIStudio.Tools.Rust;
|
||||
|
||||
namespace AIStudio.Tools.Services;
|
||||
|
||||
public sealed partial class RustService
|
||||
@ -6,35 +8,35 @@ public sealed partial class RustService
|
||||
/// <summary>
|
||||
/// Registers or updates a global keyboard shortcut.
|
||||
/// </summary>
|
||||
/// <param name="name">The name/identifier for the shortcut (e.g., "voice_recording_toggle").</param>
|
||||
/// <param name="shortcutId">The identifier for the shortcut.</param>
|
||||
/// <param name="shortcut">The shortcut string in Tauri format (e.g., "CmdOrControl+1"). Use empty string to disable.</param>
|
||||
/// <returns>True if the shortcut was registered successfully, false otherwise.</returns>
|
||||
public async Task<bool> UpdateGlobalShortcut(string name, string shortcut)
|
||||
public async Task<bool> UpdateGlobalShortcut(Shortcut shortcutId, string shortcut)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new RegisterShortcutRequest(name, shortcut);
|
||||
var request = new RegisterShortcutRequest(shortcutId, shortcut);
|
||||
var response = await this.http.PostAsJsonAsync("/shortcuts/register", request, this.jsonRustSerializerOptions);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
this.logger?.LogError("Failed to register global shortcut '{Name}' due to network error: {StatusCode}", name, response.StatusCode);
|
||||
this.logger?.LogError("Failed to register global shortcut '{ShortcutId}' due to network error: {StatusCode}", shortcutId, response.StatusCode);
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = await response.Content.ReadFromJsonAsync<ShortcutResponse>(this.jsonRustSerializerOptions);
|
||||
if (result is null || !result.Success)
|
||||
{
|
||||
this.logger?.LogError("Failed to register global shortcut '{Name}': {Error}", name, result?.ErrorMessage ?? "Unknown error");
|
||||
this.logger?.LogError("Failed to register global shortcut '{ShortcutId}': {Error}", shortcutId, result?.ErrorMessage ?? "Unknown error");
|
||||
return false;
|
||||
}
|
||||
|
||||
this.logger?.LogInformation("Global shortcut '{Name}' registered successfully with key '{Shortcut}'.", name, shortcut);
|
||||
this.logger?.LogInformation("Global shortcut '{ShortcutId}' registered successfully with key '{Shortcut}'.", shortcutId, shortcut);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.logger?.LogError(ex, "Exception while registering global shortcut '{Name}'.", name);
|
||||
this.logger?.LogError(ex, "Exception while registering global shortcut '{ShortcutId}'.", shortcutId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -136,7 +138,7 @@ public sealed partial class RustService
|
||||
}
|
||||
}
|
||||
|
||||
private sealed record RegisterShortcutRequest(string Name, string Shortcut);
|
||||
private sealed record RegisterShortcutRequest(Shortcut ShortcutId, string Shortcut);
|
||||
|
||||
private sealed record ShortcutResponse(bool Success, string ErrorMessage);
|
||||
|
||||
@ -151,5 +153,5 @@ public sealed partial class RustService
|
||||
/// <param name="IsValid">Whether the shortcut syntax is valid.</param>
|
||||
/// <param name="ErrorMessage">Error message if not valid.</param>
|
||||
/// <param name="HasConflict">Whether the shortcut conflicts with another registered shortcut.</param>
|
||||
/// <param name="ConflictDescription">Description of the conflict if any.</param>
|
||||
/// <param name="ConflictDescription">Description of the conflict, if any.</param>
|
||||
public sealed record ShortcutValidationResult(bool IsValid, string ErrorMessage, bool HasConflict, string ConflictDescription);
|
||||
|
||||
@ -29,7 +29,24 @@ static CHECK_UPDATE_RESPONSE: Lazy<Mutex<Option<UpdateResponse<tauri::Wry>>>> =
|
||||
static EVENT_BROADCAST: Lazy<Mutex<Option<broadcast::Sender<Event>>>> = Lazy::new(|| Mutex::new(None));
|
||||
|
||||
/// Stores the currently registered global shortcuts (name -> shortcut string).
|
||||
static REGISTERED_SHORTCUTS: Lazy<Mutex<HashMap<String, String>>> = Lazy::new(|| Mutex::new(HashMap::new()));
|
||||
static REGISTERED_SHORTCUTS: Lazy<Mutex<HashMap<Shortcut, String>>> = Lazy::new(|| Mutex::new(HashMap::new()));
|
||||
|
||||
/// Enum identifying global keyboard shortcuts.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum Shortcut {
|
||||
None = 0,
|
||||
VoiceRecordingToggle,
|
||||
}
|
||||
|
||||
impl Shortcut {
|
||||
/// Returns the display name for logging.
|
||||
pub fn display_name(&self) -> &'static str {
|
||||
match self {
|
||||
Shortcut::None => "none",
|
||||
Shortcut::VoiceRecordingToggle => "voice_recording_toggle",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts the Tauri app.
|
||||
pub fn start_tauri() {
|
||||
@ -686,8 +703,8 @@ pub struct FileSaveResponse {
|
||||
/// Request payload for registering a global shortcut.
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub struct RegisterShortcutRequest {
|
||||
/// The name/identifier for the shortcut (e.g., "voice_recording_toggle").
|
||||
name: String,
|
||||
/// The shortcut ID to use.
|
||||
id: Shortcut,
|
||||
|
||||
/// The shortcut string in Tauri format (e.g., "CmdOrControl+1").
|
||||
/// Use empty string to unregister the shortcut.
|
||||
@ -707,17 +724,15 @@ pub struct ShortcutResponse {
|
||||
fn register_shortcut_with_callback(
|
||||
shortcut_manager: &mut impl tauri::GlobalShortcutManager,
|
||||
shortcut: &str,
|
||||
name: &str,
|
||||
shortcut_id: Shortcut,
|
||||
event_sender: broadcast::Sender<Event>,
|
||||
) -> Result<(), tauri::Error> {
|
||||
let shortcut_name = name.to_string();
|
||||
|
||||
//
|
||||
// Match the shortcut registration to transform the Tauri result into the Rust result:
|
||||
//
|
||||
match shortcut_manager.register(shortcut, move || {
|
||||
info!(Source = "Tauri"; "Global shortcut triggered for '{shortcut_name}'.");
|
||||
let event = Event::new(TauriEventType::GlobalShortcutPressed, vec![shortcut_name.clone()]);
|
||||
info!(Source = "Tauri"; "Global shortcut triggered for '{}'.", shortcut_id.display_name());
|
||||
let event = Event::new(TauriEventType::GlobalShortcutPressed, vec![shortcut_id.to_string()]);
|
||||
let sender = event_sender.clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
match sender.send(event) {
|
||||
@ -735,10 +750,10 @@ fn register_shortcut_with_callback(
|
||||
/// the existing shortcut for that name will be unregistered.
|
||||
#[post("/shortcuts/register", data = "<payload>")]
|
||||
pub fn register_shortcut(_token: APIToken, payload: Json<RegisterShortcutRequest>) -> Json<ShortcutResponse> {
|
||||
let name = payload.name.clone();
|
||||
let id = payload.id;
|
||||
let new_shortcut = payload.shortcut.clone();
|
||||
|
||||
info!(Source = "Tauri"; "Registering global shortcut '{name}' with key '{new_shortcut}'.");
|
||||
info!(Source = "Tauri"; "Registering global shortcut '{}' with key '{new_shortcut}'.", id.display_name());
|
||||
|
||||
// Get the main window to access the global shortcut manager:
|
||||
let main_window_lock = MAIN_WINDOW.lock().unwrap();
|
||||
@ -757,10 +772,10 @@ pub fn register_shortcut(_token: APIToken, payload: Json<RegisterShortcutRequest
|
||||
let mut registered_shortcuts = REGISTERED_SHORTCUTS.lock().unwrap();
|
||||
|
||||
// Unregister the old shortcut if one exists for this name:
|
||||
if let Some(old_shortcut) = registered_shortcuts.get(&name) {
|
||||
if let Some(old_shortcut) = registered_shortcuts.get(&id) {
|
||||
if !old_shortcut.is_empty() {
|
||||
match shortcut_manager.unregister(old_shortcut.as_str()) {
|
||||
Ok(_) => info!(Source = "Tauri"; "Unregistered old shortcut '{old_shortcut}' for '{name}'."),
|
||||
Ok(_) => info!(Source = "Tauri"; "Unregistered old shortcut '{old_shortcut}' for '{}'.", id.display_name()),
|
||||
Err(error) => warn!(Source = "Tauri"; "Failed to unregister old shortcut '{old_shortcut}': {error}"),
|
||||
}
|
||||
}
|
||||
@ -768,8 +783,8 @@ pub fn register_shortcut(_token: APIToken, payload: Json<RegisterShortcutRequest
|
||||
|
||||
// When the new shortcut is empty, we're done (just unregistering):
|
||||
if new_shortcut.is_empty() {
|
||||
registered_shortcuts.remove(&name);
|
||||
info!(Source = "Tauri"; "Shortcut '{name}' has been disabled.");
|
||||
registered_shortcuts.remove(&id);
|
||||
info!(Source = "Tauri"; "Shortcut '{}' has been disabled.", id.display_name());
|
||||
return Json(ShortcutResponse {
|
||||
success: true,
|
||||
error_message: String::new(),
|
||||
@ -792,10 +807,10 @@ pub fn register_shortcut(_token: APIToken, payload: Json<RegisterShortcutRequest
|
||||
drop(event_broadcast_lock);
|
||||
|
||||
// Register the new shortcut:
|
||||
match register_shortcut_with_callback(&mut shortcut_manager, &new_shortcut, &name, event_sender) {
|
||||
match register_shortcut_with_callback(&mut shortcut_manager, &new_shortcut, id, event_sender) {
|
||||
Ok(_) => {
|
||||
info!(Source = "Tauri"; "Global shortcut '{new_shortcut}' registered successfully for '{name}'.");
|
||||
registered_shortcuts.insert(name, new_shortcut);
|
||||
info!(Source = "Tauri"; "Global shortcut '{new_shortcut}' registered successfully for '{}'.", id.display_name());
|
||||
registered_shortcuts.insert(id, new_shortcut);
|
||||
Json(ShortcutResponse {
|
||||
success: true,
|
||||
error_message: String::new(),
|
||||
@ -854,7 +869,7 @@ pub fn validate_shortcut(_token: APIToken, payload: Json<ValidateShortcutRequest
|
||||
is_valid: true,
|
||||
error_message: String::new(),
|
||||
has_conflict: true,
|
||||
conflict_description: format!("Already used by: {}", name),
|
||||
conflict_description: format!("Already used by: {}", name.display_name()),
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -909,8 +924,8 @@ pub fn suspend_shortcuts(_token: APIToken) -> Json<ShortcutResponse> {
|
||||
for (name, shortcut) in registered_shortcuts.iter() {
|
||||
if !shortcut.is_empty() {
|
||||
match shortcut_manager.unregister(shortcut.as_str()) {
|
||||
Ok(_) => info!(Source = "Tauri"; "Temporarily unregistered shortcut '{shortcut}' for '{name}'."),
|
||||
Err(error) => warn!(Source = "Tauri"; "Failed to unregister shortcut '{shortcut}' for '{name}': {error}"),
|
||||
Ok(_) => info!(Source = "Tauri"; "Temporarily unregistered shortcut '{shortcut}' for '{}'.", name.display_name()),
|
||||
Err(error) => warn!(Source = "Tauri"; "Failed to unregister shortcut '{shortcut}' for '{}': {error}", name.display_name()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -958,18 +973,18 @@ pub fn resume_shortcuts(_token: APIToken) -> Json<ShortcutResponse> {
|
||||
|
||||
// Re-register all shortcuts with the OS:
|
||||
let mut success_count = 0;
|
||||
for (name, shortcut) in registered_shortcuts.iter() {
|
||||
for (shortcut_id, shortcut) in registered_shortcuts.iter() {
|
||||
if shortcut.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
match register_shortcut_with_callback(&mut shortcut_manager, shortcut, name, event_sender.clone()) {
|
||||
match register_shortcut_with_callback(&mut shortcut_manager, shortcut, *shortcut_id, event_sender.clone()) {
|
||||
Ok(_) => {
|
||||
info!(Source = "Tauri"; "Re-registered shortcut '{shortcut}' for '{name}'.");
|
||||
info!(Source = "Tauri"; "Re-registered shortcut '{shortcut}' for '{}'.", shortcut_id.display_name());
|
||||
success_count += 1;
|
||||
},
|
||||
|
||||
Err(error) => warn!(Source = "Tauri"; "Failed to re-register shortcut '{shortcut}' for '{name}': {error}"),
|
||||
Err(error) => warn!(Source = "Tauri"; "Failed to re-register shortcut '{shortcut}' for '{}': {error}", shortcut_id.display_name()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user