diff --git a/app/MindWork AI Studio/Program.cs b/app/MindWork AI Studio/Program.cs index a4d9c2b4..2514a67f 100644 --- a/app/MindWork AI Studio/Program.cs +++ b/app/MindWork AI Studio/Program.cs @@ -133,6 +133,11 @@ internal sealed class Program builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); + + // ReSharper disable AccessToDisposedClosure + builder.Services.AddHostedService(_ => rust); + // ReSharper restore AccessToDisposedClosure + builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddHubOptions(options => diff --git a/app/MindWork AI Studio/Tools/Event.cs b/app/MindWork AI Studio/Tools/Event.cs index 8d8ce415..9f612f04 100644 --- a/app/MindWork AI Studio/Tools/Event.cs +++ b/app/MindWork AI Studio/Tools/Event.cs @@ -14,6 +14,7 @@ public enum Event SHOW_ERROR, SHOW_WARNING, SHOW_SUCCESS, + TAURI_EVENT_RECEIVED, // Update events: USER_SEARCH_FOR_UPDATE, diff --git a/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs b/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs new file mode 100644 index 00000000..140522be --- /dev/null +++ b/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs @@ -0,0 +1,3 @@ +namespace AIStudio.Tools.Rust; + +public readonly record struct TauriEvent(TauriEventType Type, List Payload); \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs b/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs new file mode 100644 index 00000000..2710c16b --- /dev/null +++ b/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs @@ -0,0 +1,11 @@ +namespace AIStudio.Tools.Rust; + +public enum TauriEventType +{ + WINDOW_FOCUSED, + WINDOW_NOT_FOCUSED, + + FILE_DROP_HOVERED, + FILE_DROP_DROPPED, + FILE_DROP_CANCELED, +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Services/RustService.Events.cs b/app/MindWork AI Studio/Tools/Services/RustService.Events.cs new file mode 100644 index 00000000..539c3d06 --- /dev/null +++ b/app/MindWork AI Studio/Tools/Services/RustService.Events.cs @@ -0,0 +1,53 @@ +using System.Text.Json; + +using AIStudio.Tools.Rust; + +namespace AIStudio.Tools.Services; + +public partial class RustService +{ + private async Task StartStreamTauriEvents(CancellationToken stopToken) + { + try + { + while (!stopToken.IsCancellationRequested) + { + try + { + await using var stream = await this.http.GetStreamAsync("/events", stopToken); + using var reader = new StreamReader(stream); + while(!reader.EndOfStream) + { + var line = await reader.ReadLineAsync(stopToken); + if (string.IsNullOrWhiteSpace(line)) + continue; + + var tauriEvent = JsonSerializer.Deserialize(line, this.jsonRustSerializerOptions); + if (tauriEvent != default) + await MessageBus.INSTANCE.SendMessage(null, Event.TAURI_EVENT_RECEIVED, tauriEvent); + } + } + + // The cancellation token was triggered, exit the loop: + catch (OperationCanceledException) + { + break; + } + + // Some other error occurred, log it and retry after a delay: + catch (Exception e) + { + this.logger!.LogError("Error while streaming Tauri events: {Message}", e.Message); + await Task.Delay(TimeSpan.FromSeconds(3), stopToken); + } + } + } + + // The cancellation token was triggered, exit the method: + catch (OperationCanceledException) + { + } + + this.logger!.LogWarning("Stopped streaming Tauri events."); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Services/RustService.cs b/app/MindWork AI Studio/Tools/Services/RustService.cs index 38fab8cc..56032b65 100644 --- a/app/MindWork AI Studio/Tools/Services/RustService.cs +++ b/app/MindWork AI Studio/Tools/Services/RustService.cs @@ -8,7 +8,7 @@ namespace AIStudio.Tools.Services; /// /// Calling Rust functions. /// -public sealed partial class RustService : IDisposable +public sealed partial class RustService : BackgroundService { private readonly HttpClient http; @@ -59,11 +59,18 @@ public sealed partial class RustService : IDisposable this.encryptor = encryptionService; } - #region IDisposable + #region Overrides of BackgroundService - public void Dispose() + protected override async Task ExecuteAsync(CancellationToken stopToken) + { + this.logger?.LogInformation("The Rust service was initialized."); + await this.StartStreamTauriEvents(stopToken); + } + + public override void Dispose() { this.http.Dispose(); + base.Dispose(); } #endregion