|
|
|
@ -1,28 +1,41 @@
|
|
|
|
|
using System; |
|
|
|
|
using System.IO; |
|
|
|
|
using System.Linq; |
|
|
|
|
using System.Text.Json; |
|
|
|
|
using System.Threading.Tasks; |
|
|
|
|
using AsyncAwaitBestPractices; |
|
|
|
|
using Avalonia.Controls; |
|
|
|
|
using Avalonia.Platform.Storage; |
|
|
|
|
using CommunityToolkit.Mvvm.ComponentModel; |
|
|
|
|
using CommunityToolkit.Mvvm.Input; |
|
|
|
|
using DynamicData; |
|
|
|
|
using DynamicData.Binding; |
|
|
|
|
using FluentAvalonia.UI.Controls; |
|
|
|
|
using StabilityMatrix.Avalonia.Controls; |
|
|
|
|
using StabilityMatrix.Avalonia.Languages; |
|
|
|
|
using StabilityMatrix.Avalonia.Models; |
|
|
|
|
using StabilityMatrix.Avalonia.Services; |
|
|
|
|
using StabilityMatrix.Avalonia.ViewModels.Base; |
|
|
|
|
using StabilityMatrix.Avalonia.Views; |
|
|
|
|
using StabilityMatrix.Core.Attributes; |
|
|
|
|
using StabilityMatrix.Core.Helper; |
|
|
|
|
using StabilityMatrix.Core.Models.Api.OpenArt; |
|
|
|
|
using StabilityMatrix.Core.Processes; |
|
|
|
|
using StabilityMatrix.Core.Services; |
|
|
|
|
|
|
|
|
|
namespace StabilityMatrix.Avalonia.ViewModels; |
|
|
|
|
|
|
|
|
|
[View(typeof(InstalledWorkflowsPage))] |
|
|
|
|
[Singleton] |
|
|
|
|
public partial class InstalledWorkflowsViewModel(ISettingsManager settingsManager) : TabViewModelBase |
|
|
|
|
public partial class InstalledWorkflowsViewModel( |
|
|
|
|
ISettingsManager settingsManager, |
|
|
|
|
INotificationService notificationService |
|
|
|
|
) : TabViewModelBase, IDisposable |
|
|
|
|
{ |
|
|
|
|
public override string Header => "Installed Workflows"; |
|
|
|
|
public override string Header => Resources.TabLabel_InstalledWorkflows; |
|
|
|
|
|
|
|
|
|
private readonly SourceCache<OpenArtMetadata, string> workflowsCache = new(x => x.Id); |
|
|
|
|
private readonly SourceCache<OpenArtMetadata, string> workflowsCache = |
|
|
|
|
new(x => x.Workflow?.Id ?? Guid.NewGuid().ToString()); |
|
|
|
|
|
|
|
|
|
[ObservableProperty] |
|
|
|
|
private IObservableCollection<OpenArtMetadata> displayedWorkflows = |
|
|
|
@ -38,6 +51,7 @@ public partial class InstalledWorkflowsViewModel(ISettingsManager settingsManage
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
await LoadInstalledWorkflowsAsync(); |
|
|
|
|
EventManager.Instance.WorkflowInstalled += OnWorkflowInstalled; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[RelayCommand] |
|
|
|
@ -58,12 +72,15 @@ public partial class InstalledWorkflowsViewModel(ISettingsManager settingsManage
|
|
|
|
|
var json = await File.ReadAllTextAsync(workflowPath); |
|
|
|
|
var metadata = JsonSerializer.Deserialize<OpenArtMetadata>(json); |
|
|
|
|
|
|
|
|
|
if (metadata?.Id == null) |
|
|
|
|
if (metadata?.Workflow == null) |
|
|
|
|
{ |
|
|
|
|
metadata = new OpenArtMetadata |
|
|
|
|
{ |
|
|
|
|
Id = Guid.NewGuid().ToString(), |
|
|
|
|
Name = Path.GetFileNameWithoutExtension(workflowPath) |
|
|
|
|
Workflow = new OpenArtSearchResult |
|
|
|
|
{ |
|
|
|
|
Id = Guid.NewGuid().ToString(), |
|
|
|
|
Name = Path.GetFileNameWithoutExtension(workflowPath) |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -76,4 +93,76 @@ public partial class InstalledWorkflowsViewModel(ISettingsManager settingsManage
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[RelayCommand] |
|
|
|
|
private async Task OpenInExplorer(OpenArtMetadata metadata) |
|
|
|
|
{ |
|
|
|
|
if (metadata.FilePath == null) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
var path = metadata.FilePath.FirstOrDefault()?.Path.ToString(); |
|
|
|
|
if (string.IsNullOrWhiteSpace(path)) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
await ProcessRunner.OpenFileBrowser(path); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[RelayCommand] |
|
|
|
|
private void OpenOnOpenArt(OpenArtMetadata metadata) |
|
|
|
|
{ |
|
|
|
|
if (metadata.Workflow == null) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
ProcessRunner.OpenUrl($"https://openart.ai/workflows/{metadata.Workflow.Id}"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[RelayCommand] |
|
|
|
|
private async Task DeleteAsync(OpenArtMetadata metadata) |
|
|
|
|
{ |
|
|
|
|
var confirmationDialog = new BetterContentDialog |
|
|
|
|
{ |
|
|
|
|
Title = Resources.Label_AreYouSure, |
|
|
|
|
Content = Resources.Label_ActionCannotBeUndone, |
|
|
|
|
PrimaryButtonText = Resources.Action_Delete, |
|
|
|
|
SecondaryButtonText = Resources.Action_Cancel, |
|
|
|
|
DefaultButton = ContentDialogButton.Primary, |
|
|
|
|
IsSecondaryButtonEnabled = true, |
|
|
|
|
}; |
|
|
|
|
var dialogResult = await confirmationDialog.ShowAsync(); |
|
|
|
|
if (dialogResult != ContentDialogResult.Primary) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
await using var delay = new MinimumDelay(200, 500); |
|
|
|
|
|
|
|
|
|
var path = metadata?.FilePath?.FirstOrDefault()?.Path.ToString().Replace("file:///", ""); |
|
|
|
|
if (!string.IsNullOrWhiteSpace(path) && File.Exists(path)) |
|
|
|
|
{ |
|
|
|
|
await notificationService.TryAsync( |
|
|
|
|
Task.Run(() => File.Delete(path)), |
|
|
|
|
message: "Error deleting workflow" |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
var id = metadata?.Workflow?.Id; |
|
|
|
|
if (!string.IsNullOrWhiteSpace(id)) |
|
|
|
|
{ |
|
|
|
|
workflowsCache.Remove(id); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
notificationService.Show( |
|
|
|
|
Resources.Label_WorkflowDeleted, |
|
|
|
|
string.Format(Resources.Label_WorkflowDeletedSuccessfully, metadata?.Workflow?.Name) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void OnWorkflowInstalled(object? sender, EventArgs e) |
|
|
|
|
{ |
|
|
|
|
LoadInstalledWorkflowsAsync().SafeFireAndForget(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void Dispose() |
|
|
|
|
{ |
|
|
|
|
workflowsCache.Dispose(); |
|
|
|
|
EventManager.Instance.WorkflowInstalled -= OnWorkflowInstalled; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|