Refactor components (#80)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2024-08-21 08:30:01 +02:00
1 parent a18cb22263
commit 1d1af91f3e
137 files changed
+220 -220

No files matched your search

@@ -0,0 +1,22 @@
// ReSharper disable ClassNeverInstantiated.Global
namespace AIStudio.Tools.Services;
/// <summary>
/// Wire up the clipboard service to copy Markdown to the clipboard.
/// We use our own Rust-based clipboard service for this.
/// </summary>
public sealed class MarkdownClipboardService(Rust rust, IJSRuntime jsRuntime, ISnackbar snackbar) : IMudMarkdownClipboardService
{
private IJSRuntime JsRuntime { get; } = jsRuntime;
private ISnackbar Snackbar { get; } = snackbar;
private Rust Rust { get; } = rust;
/// <summary>
/// Gets called when the user wants to copy the markdown to the clipboard.
/// </summary>
/// <param name="text">The Markdown text to copy.</param>
public async ValueTask CopyToClipboardAsync(string text) => await this.Rust.CopyText2Clipboard(this.JsRuntime, this.Snackbar, text);
}
@@ -0,0 +1,72 @@
using AIStudio.Settings;
using AIStudio.Settings.DataModel;
namespace AIStudio.Tools.Services;
public class TemporaryChatService(SettingsManager settingsManager) : BackgroundService
{
private static readonly TimeSpan CHECK_INTERVAL = TimeSpan.FromDays(1);
private static bool IS_INITIALIZED;
#region Overrides of BackgroundService
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested && !IS_INITIALIZED)
await Task.Delay(TimeSpan.FromSeconds(3), stoppingToken);
await settingsManager.LoadSettings();
if(settingsManager.ConfigurationData.Workspace.StorageTemporaryMaintenancePolicy is WorkspaceStorageTemporaryMaintenancePolicy.NO_AUTOMATIC_MAINTENANCE)
{
Console.WriteLine("Automatic maintenance of temporary chat storage is disabled. Exiting maintenance service.");
return;
}
await this.StartMaintenance();
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(CHECK_INTERVAL, stoppingToken);
await this.StartMaintenance();
}
}
#endregion
private Task StartMaintenance()
{
var temporaryDirectories = Path.Join(SettingsManager.DataDirectory, "tempChats");
if(!Directory.Exists(temporaryDirectories))
return Task.CompletedTask;
foreach (var tempChatDirPath in Directory.EnumerateDirectories(temporaryDirectories))
{
var chatPath = Path.Join(tempChatDirPath, "thread.json");
var chatMetadata = new FileInfo(chatPath);
if (!chatMetadata.Exists)
continue;
var lastWriteTime = chatMetadata.LastWriteTimeUtc;
var deleteChat = settingsManager.ConfigurationData.Workspace.StorageTemporaryMaintenancePolicy switch
{
WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_7_DAYS => DateTime.UtcNow - lastWriteTime > TimeSpan.FromDays(7),
WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_30_DAYS => DateTime.UtcNow - lastWriteTime > TimeSpan.FromDays(30),
WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_90_DAYS => DateTime.UtcNow - lastWriteTime > TimeSpan.FromDays(90),
WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_180_DAYS => DateTime.UtcNow - lastWriteTime > TimeSpan.FromDays(180),
WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_365_DAYS => DateTime.UtcNow - lastWriteTime > TimeSpan.FromDays(365),
WorkspaceStorageTemporaryMaintenancePolicy.NO_AUTOMATIC_MAINTENANCE => false,
_ => false,
};
if(deleteChat)
Directory.Delete(tempChatDirPath, true);
}
return Task.CompletedTask;
}
public static void Initialize()
{
IS_INITIALIZED = true;
}
}
@@ -0,0 +1,124 @@
using AIStudio.Settings;
using AIStudio.Settings.DataModel;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Tools.Services;
public sealed class UpdateService : BackgroundService, IMessageBusReceiver
{
// We cannot inject IJSRuntime into our service. This is because
// the service is not a Blazor component. We need to pass the IJSRuntime from
// the MainLayout component to the service.
private static IJSRuntime? JS_RUNTIME;
private static bool IS_INITIALIZED;
private static ISnackbar? SNACKBAR;
private readonly SettingsManager settingsManager;
private readonly MessageBus messageBus;
private readonly Rust rust;
private TimeSpan updateInterval;
public UpdateService(MessageBus messageBus, SettingsManager settingsManager, Rust rust)
{
this.settingsManager = settingsManager;
this.messageBus = messageBus;
this.rust = rust;
this.messageBus.RegisterComponent(this);
this.ApplyFilters([], [ Event.USER_SEARCH_FOR_UPDATE ]);
}
#region Overrides of BackgroundService
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested && !IS_INITIALIZED)
await Task.Delay(TimeSpan.FromSeconds(3), stoppingToken);
this.updateInterval = this.settingsManager.ConfigurationData.App.UpdateBehavior switch
{
UpdateBehavior.NO_CHECK => Timeout.InfiniteTimeSpan,
UpdateBehavior.ONCE_STARTUP => Timeout.InfiniteTimeSpan,
UpdateBehavior.HOURLY => TimeSpan.FromHours(1),
UpdateBehavior.DAILY => TimeSpan.FromDays(1),
UpdateBehavior.WEEKLY => TimeSpan.FromDays(7),
_ => TimeSpan.FromHours(1)
};
if(this.settingsManager.ConfigurationData.App.UpdateBehavior is UpdateBehavior.NO_CHECK)
return;
await this.CheckForUpdate();
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(this.updateInterval, stoppingToken);
await this.CheckForUpdate();
}
}
#endregion
#region Implementation of IMessageBusReceiver
public async Task ProcessMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data)
{
switch (triggeredEvent)
{
case Event.USER_SEARCH_FOR_UPDATE:
await this.CheckForUpdate(notifyUserWhenNoUpdate: true);
break;
}
}
public Task<TResult?> ProcessMessageWithResult<TPayload, TResult>(ComponentBase? sendingComponent, Event triggeredEvent, TPayload? data)
{
return Task.FromResult<TResult?>(default);
}
#endregion
#region Overrides of BackgroundService
public override async Task StopAsync(CancellationToken cancellationToken)
{
this.messageBus.Unregister(this);
await base.StopAsync(cancellationToken);
}
#endregion
private async Task CheckForUpdate(bool notifyUserWhenNoUpdate = false)
{
if(!IS_INITIALIZED)
return;
var response = await this.rust.CheckForUpdate(JS_RUNTIME!);
if (response.UpdateIsAvailable)
{
await this.messageBus.SendMessage(null, Event.UPDATE_AVAILABLE, response);
}
else
{
if (notifyUserWhenNoUpdate)
{
SNACKBAR!.Add("No update found.", Severity.Normal, config =>
{
config.Icon = Icons.Material.Filled.Update;
config.IconSize = Size.Large;
config.IconColor = Color.Primary;
});
}
}
}
public static void SetBlazorDependencies(IJSRuntime jsRuntime, ISnackbar snackbar)
{
SNACKBAR = snackbar;
JS_RUNTIME = jsRuntime;
IS_INITIALIZED = true;
}
}