Improved issue handling

This commit is contained in:
Thorsten Sommer 2026-01-18 20:44:08 +01:00
parent cc3560fdd2
commit ce7a334fef
Signed by untrusted user who does not match committer: tsommer
GPG Key ID: 371BBA77A02C0108

View File

@ -25,9 +25,16 @@ public partial class VoiceRecorder : MSGComponentBase
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
await base.OnInitializedAsync(); await base.OnInitializedAsync();
// Initialize sound effects. This "warms up" the AudioContext and preloads all sounds for reliable playback: try
await this.JsRuntime.InvokeVoidAsync("initSoundEffects"); {
// Initialize sound effects. This "warms up" the AudioContext and preloads all sounds for reliable playback:
await this.JsRuntime.InvokeVoidAsync("initSoundEffects");
}
catch (Exception ex)
{
this.Logger.LogError(ex, "Failed to initialize sound effects.");
}
} }
#endregion #endregion
@ -51,9 +58,16 @@ public partial class VoiceRecorder : MSGComponentBase
{ {
if (toggled) if (toggled)
{ {
// Warm up sound effects: try
await this.JsRuntime.InvokeVoidAsync("initSoundEffects"); {
// Warm up sound effects:
await this.JsRuntime.InvokeVoidAsync("initSoundEffects");
}
catch (Exception ex)
{
this.Logger.LogError(ex, "Failed to initialize sound effects.");
}
var mimeTypes = GetPreferredMimeTypes( var mimeTypes = GetPreferredMimeTypes(
Builder.Create().UseAudio().UseSubtype(AudioSubtype.OGG).Build(), Builder.Create().UseAudio().UseSubtype(AudioSubtype.OGG).Build(),
Builder.Create().UseAudio().UseSubtype(AudioSubtype.AAC).Build(), Builder.Create().UseAudio().UseSubtype(AudioSubtype.AAC).Build(),
@ -71,20 +85,39 @@ public partial class VoiceRecorder : MSGComponentBase
// Initialize the file stream for writing chunks: // Initialize the file stream for writing chunks:
await this.InitializeRecordingStream(); await this.InitializeRecordingStream();
var mimeTypeStrings = mimeTypes.ToStringArray(); try
var actualMimeType = await this.JsRuntime.InvokeAsync<string>("audioRecorder.start", this.dotNetReference, mimeTypeStrings); {
var mimeTypeStrings = mimeTypes.ToStringArray();
var actualMimeType = await this.JsRuntime.InvokeAsync<string>("audioRecorder.start", this.dotNetReference, mimeTypeStrings);
// Store the MIME type for later use: // Store the MIME type for later use:
this.currentRecordingMimeType = actualMimeType; this.currentRecordingMimeType = actualMimeType;
this.Logger.LogInformation("Audio recording started with MIME type: '{ActualMimeType}'.", actualMimeType); this.Logger.LogInformation("Audio recording started with MIME type: '{ActualMimeType}'.", actualMimeType);
this.isRecording = true; this.isRecording = true;
}
catch (Exception e)
{
this.Logger.LogError(e, "Failed to start audio recording.");
await this.MessageBus.SendError(new(Icons.Material.Filled.MicOff, this.T("Failed to start audio recording.")));
// Clean up the recording stream if starting failed:
await this.FinalizeRecordingStream();
}
} }
else else
{ {
var result = await this.JsRuntime.InvokeAsync<AudioRecordingResult>("audioRecorder.stop"); try
if (result.ChangedMimeType) {
this.Logger.LogWarning("The recorded audio MIME type was changed to '{ResultMimeType}'.", result.MimeType); var result = await this.JsRuntime.InvokeAsync<AudioRecordingResult>("audioRecorder.stop");
if (result.ChangedMimeType)
this.Logger.LogWarning("The recorded audio MIME type was changed to '{ResultMimeType}'.", result.MimeType);
}
catch (Exception e)
{
this.Logger.LogError(e, "Failed to stop audio recording.");
await this.MessageBus.SendError(new(Icons.Material.Filled.MicOff, this.T("Failed to stop audio recording.")));
}
// Close and finalize the recording stream: // Close and finalize the recording stream:
await this.FinalizeRecordingStream(); await this.FinalizeRecordingStream();
@ -280,8 +313,15 @@ public partial class VoiceRecorder : MSGComponentBase
this.Logger.LogInformation("Transcription completed successfully. Result length: {Length} characters.", transcribedText.Length); this.Logger.LogInformation("Transcription completed successfully. Result length: {Length} characters.", transcribedText.Length);
// Play the transcription done sound effect: try
await this.JsRuntime.InvokeVoidAsync("playSound", "/sounds/transcription_done.ogg"); {
// Play the transcription done sound effect:
await this.JsRuntime.InvokeVoidAsync("playSound", "/sounds/transcription_done.ogg");
}
catch (Exception ex)
{
this.Logger.LogError(ex, "Failed to play transcription done sound effect.");
}
// Copy the transcribed text to the clipboard: // Copy the transcribed text to the clipboard:
await this.RustService.CopyText2Clipboard(this.Snackbar, transcribedText); await this.RustService.CopyText2Clipboard(this.Snackbar, transcribedText);
@ -320,7 +360,15 @@ public partial class VoiceRecorder : MSGComponentBase
// Wait a moment for any queued sounds to finish playing, then release the microphone. // Wait a moment for any queued sounds to finish playing, then release the microphone.
// This allows Bluetooth headsets to switch back to A2DP profile without interrupting audio: // This allows Bluetooth headsets to switch back to A2DP profile without interrupting audio:
await Task.Delay(1_800); await Task.Delay(1_800);
await this.JsRuntime.InvokeVoidAsync("audioRecorder.releaseMicrophone");
try
{
await this.JsRuntime.InvokeVoidAsync("audioRecorder.releaseMicrophone");
}
catch (Exception e)
{
this.Logger.LogError(e, "Failed to release the microphone.");
}
} }
private sealed class AudioRecordingResult private sealed class AudioRecordingResult