Browse Source

moved strings to resources & added send to img2img/vid options in output browser

pull/438/head
JT 11 months ago
parent
commit
7ef86731a6
  1. 10
      StabilityMatrix.Avalonia/Controls/VideoGenerationSettingsCard.axaml
  2. 8
      StabilityMatrix.Avalonia/Controls/VideoOutputSettingsCard.axaml
  3. 2
      StabilityMatrix.Avalonia/FallbackRamCachedWebImageLoader.cs
  4. 81
      StabilityMatrix.Avalonia/Languages/Resources.Designer.cs
  5. 27
      StabilityMatrix.Avalonia/Languages/Resources.resx
  6. 159
      StabilityMatrix.Avalonia/ViewModels/InferenceViewModel.cs
  7. 12
      StabilityMatrix.Avalonia/ViewModels/OutputsPageViewModel.cs
  8. 16
      StabilityMatrix.Avalonia/Views/OutputsPage.axaml
  9. 23
      StabilityMatrix.Core/Helper/EventManager.cs
  10. 2
      StabilityMatrix.Core/Models/Database/LocalImageFile.cs

10
StabilityMatrix.Avalonia/Controls/VideoGenerationSettingsCard.axaml

@ -24,7 +24,7 @@
Grid.Column="0"
Margin="0,0,8,0"
VerticalAlignment="Center"
Text="Frames" />
Text="{x:Static lang:Resources.Label_Frames}" />
<controls1:NumberBox
Grid.Row="0"
Grid.Column="1"
@ -41,7 +41,7 @@
Grid.Column="0"
Margin="0,8,8,0"
VerticalAlignment="Center"
Text="Frames Per Second" />
Text="{x:Static lang:Resources.Label_Fps}" />
<controls1:NumberBox
Grid.Row="1"
Grid.Column="1"
@ -58,7 +58,7 @@
Grid.Column="0"
Margin="0,8,8,0"
VerticalAlignment="Center"
Text="Min CFG" />
Text="{x:Static lang:Resources.Label_MinCfg}" />
<controls1:NumberBox
Margin="8,8,0,0"
Grid.Row="2"
@ -75,7 +75,7 @@
Grid.Row="3"
Grid.Column="0"
VerticalAlignment="Center"
Text="Motion Bucket ID" />
Text="{x:Static lang:Resources.Label_MotionBucketId}" />
<controls1:NumberBox
Margin="8,8,0,0"
Grid.Row="3"
@ -94,7 +94,7 @@
<Grid ColumnDefinitions="*,Auto">
<TextBlock
VerticalAlignment="Center"
Text="Augmentation Level"/>
Text="{x:Static lang:Resources.Label_AugmentationLevel}" />
<controls1:NumberBox
Grid.Column="1"
Margin="4,0,0,0"

8
StabilityMatrix.Avalonia/Controls/VideoOutputSettingsCard.axaml

@ -34,7 +34,7 @@
Grid.Column="0"
Margin="0,0,8,0"
VerticalAlignment="Center"
Text="Frames Per Second" />
Text="{x:Static lang:Resources.Label_Fps}" />
<controls1:NumberBox
Grid.Row="1"
Grid.Column="1"
@ -51,7 +51,7 @@
Grid.Column="0"
Margin="0,8,8,0"
VerticalAlignment="Center"
Text="Lossless" />
Text="{x:Static lang:Resources.Label_Lossless}" />
<CheckBox
Grid.Row="2"
Grid.Column="1"
@ -64,7 +64,7 @@
Grid.Column="0"
Margin="0,8,8,0"
VerticalAlignment="Center"
Text="Quality" />
Text="{x:Static lang:Resources.Label_VideoQuality}" />
<controls1:NumberBox
Margin="8,8,0,0"
Grid.Row="3"
@ -82,7 +82,7 @@
Grid.Row="4"
Grid.Column="0"
VerticalAlignment="Center"
Text="Method" />
Text="{x:Static lang:Resources.Label_VideoOutputMethod}" />
<ComboBox
Grid.Row="4"
Grid.Column="1"

2
StabilityMatrix.Avalonia/FallbackRamCachedWebImageLoader.cs

@ -1,9 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using AsyncAwaitBestPractices;
using AsyncImageLoader.Loaders;

81
StabilityMatrix.Avalonia/Languages/Resources.Designer.cs generated

@ -707,6 +707,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Augmentation Level.
/// </summary>
public static string Label_AugmentationLevel {
get {
return ResourceManager.GetString("Label_AugmentationLevel", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Auto Completion.
/// </summary>
@ -1193,6 +1202,24 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Frames Per Second.
/// </summary>
public static string Label_Fps {
get {
return ResourceManager.GetString("Label_Fps", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Frames.
/// </summary>
public static string Label_Frames {
get {
return ResourceManager.GetString("Label_Frames", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to General.
/// </summary>
@ -1238,6 +1265,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Image to Video.
/// </summary>
public static string Label_ImageToVideo {
get {
return ResourceManager.GetString("Label_ImageToVideo", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Image Viewer.
/// </summary>
@ -1436,6 +1472,24 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Lossless.
/// </summary>
public static string Label_Lossless {
get {
return ResourceManager.GetString("Label_Lossless", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Min CFG.
/// </summary>
public static string Label_MinCfg {
get {
return ResourceManager.GetString("Label_MinCfg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Missing Image File.
/// </summary>
@ -1490,6 +1544,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Motion Bucket ID.
/// </summary>
public static string Label_MotionBucketId {
get {
return ResourceManager.GetString("Label_MotionBucketId", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Networks (Lora / LyCORIS).
/// </summary>
@ -2165,6 +2228,24 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Method.
/// </summary>
public static string Label_VideoOutputMethod {
get {
return ResourceManager.GetString("Label_VideoOutputMethod", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Quality.
/// </summary>
public static string Label_VideoQuality {
get {
return ResourceManager.GetString("Label_VideoQuality", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Waiting to connect....
/// </summary>

27
StabilityMatrix.Avalonia/Languages/Resources.resx

@ -900,4 +900,31 @@
<data name="Label_CLIPSkip" xml:space="preserve">
<value>CLIP Skip</value>
</data>
<data name="Label_ImageToVideo" xml:space="preserve">
<value>Image to Video</value>
</data>
<data name="Label_Fps" xml:space="preserve">
<value>Frames Per Second</value>
</data>
<data name="Label_MinCfg" xml:space="preserve">
<value>Min CFG</value>
</data>
<data name="Label_Lossless" xml:space="preserve">
<value>Lossless</value>
</data>
<data name="Label_Frames" xml:space="preserve">
<value>Frames</value>
</data>
<data name="Label_MotionBucketId" xml:space="preserve">
<value>Motion Bucket ID</value>
</data>
<data name="Label_AugmentationLevel" xml:space="preserve">
<value>Augmentation Level</value>
</data>
<data name="Label_VideoOutputMethod" xml:space="preserve">
<value>Method</value>
</data>
<data name="Label_VideoQuality" xml:space="preserve">
<value>Quality</value>
</data>
</root>

159
StabilityMatrix.Avalonia/ViewModels/InferenceViewModel.cs

@ -53,7 +53,8 @@ public partial class InferenceViewModel : PageViewModelBase, IAsyncDisposable
private readonly ILiteDbContext liteDbContext;
public override string Title => "Inference";
public override IconSource IconSource => new SymbolIconSource { Symbol = Symbol.AppGeneric, IsFilled = true };
public override IconSource IconSource =>
new SymbolIconSource { Symbol = Symbol.AppGeneric, IsFilled = true };
public RefreshBadgeViewModel ConnectionBadge { get; } =
new()
@ -110,6 +111,8 @@ public partial class InferenceViewModel : PageViewModelBase, IAsyncDisposable
// "Send to Inference"
EventManager.Instance.InferenceTextToImageRequested += OnInferenceTextToImageRequested;
EventManager.Instance.InferenceUpscaleRequested += OnInferenceUpscaleRequested;
EventManager.Instance.InferenceImageToImageRequested += OnInferenceImageToImageRequested;
EventManager.Instance.InferenceImageToVideoRequested += OnInferenceImageToVideoRequested;
MenuSaveAsCommand.WithConditionalNotificationErrorHandler(notificationService);
MenuOpenProjectCommand.WithConditionalNotificationErrorHandler(notificationService);
@ -126,47 +129,43 @@ public partial class InferenceViewModel : PageViewModelBase, IAsyncDisposable
IDisposable? onStartupComplete = null;
Dispatcher
.UIThread
.Post(() =>
Dispatcher.UIThread.Post(() =>
{
if (e.CurrentPackagePair?.BasePackage is ComfyUI package)
{
if (e.CurrentPackagePair?.BasePackage is ComfyUI package)
{
IsWaitingForConnection = true;
onStartupComplete = Observable
.FromEventPattern<string>(package, nameof(package.StartupComplete))
.Take(1)
.Subscribe(_ =>
IsWaitingForConnection = true;
onStartupComplete = Observable
.FromEventPattern<string>(package, nameof(package.StartupComplete))
.Take(1)
.Subscribe(_ =>
{
Dispatcher.UIThread.Post(() =>
{
Dispatcher
.UIThread
.Post(() =>
{
if (ConnectCommand.CanExecute(null))
{
Logger.Trace("On package launch - starting connection");
ConnectCommand.Execute(null);
}
IsWaitingForConnection = false;
});
if (ConnectCommand.CanExecute(null))
{
Logger.Trace("On package launch - starting connection");
ConnectCommand.Execute(null);
}
IsWaitingForConnection = false;
});
}
else
});
}
else
{
// Cancel any pending connection
if (ConnectCancelCommand.CanExecute(null))
{
// Cancel any pending connection
if (ConnectCancelCommand.CanExecute(null))
{
ConnectCancelCommand.Execute(null);
}
onStartupComplete?.Dispose();
onStartupComplete = null;
IsWaitingForConnection = false;
// Disconnect
Logger.Trace("On package close - disconnecting");
DisconnectCommand.Execute(null);
ConnectCancelCommand.Execute(null);
}
});
onStartupComplete?.Dispose();
onStartupComplete = null;
IsWaitingForConnection = false;
// Disconnect
Logger.Trace("On package close - disconnecting");
DisconnectCommand.Execute(null);
}
});
}
public override void OnLoaded()
@ -216,9 +215,14 @@ public partial class InferenceViewModel : PageViewModelBase, IAsyncDisposable
);
// Set not open
await liteDbContext
.InferenceProjects
.UpdateAsync(project with { IsOpen = false, IsSelected = false, CurrentTabIndex = -1 });
await liteDbContext.InferenceProjects.UpdateAsync(
project with
{
IsOpen = false,
IsSelected = false,
CurrentTabIndex = -1
}
);
}
}
}
@ -249,6 +253,16 @@ public partial class InferenceViewModel : PageViewModelBase, IAsyncDisposable
Dispatcher.UIThread.Post(() => AddUpscalerTabFromImage(e).SafeFireAndForget());
}
private void OnInferenceImageToImageRequested(object? sender, LocalImageFile e)
{
Dispatcher.UIThread.Post(() => AddImageToImageFromImage(e).SafeFireAndForget());
}
private void OnInferenceImageToVideoRequested(object? sender, LocalImageFile e)
{
Dispatcher.UIThread.Post(() => AddImageToVideoFromImage(e).SafeFireAndForget());
}
/// <summary>
/// Update the database with current tabs
/// </summary>
@ -272,7 +286,11 @@ public partial class InferenceViewModel : PageViewModelBase, IAsyncDisposable
entry.IsOpen = tab == SelectedTab;
entry.CurrentTabIndex = i;
Logger.Trace("SyncTabStatesWithDatabase updated entry for tab '{Title}': {@Entry}", tab.TabTitle, entry);
Logger.Trace(
"SyncTabStatesWithDatabase updated entry for tab '{Title}': {@Entry}",
tab.TabTitle,
entry
);
await liteDbContext.InferenceProjects.UpsertAsync(entry);
}
}
@ -287,7 +305,9 @@ public partial class InferenceViewModel : PageViewModelBase, IAsyncDisposable
return;
}
var entry = await liteDbContext.InferenceProjects.FindOneAsync(p => p.FilePath == projectFile.ToString());
var entry = await liteDbContext.InferenceProjects.FindOneAsync(
p => p.FilePath == projectFile.ToString()
);
// Create if not found
entry ??= new InferenceProjectEntry { Id = Guid.NewGuid(), FilePath = projectFile.ToString() };
@ -295,7 +315,11 @@ public partial class InferenceViewModel : PageViewModelBase, IAsyncDisposable
entry.IsOpen = tab == SelectedTab;
entry.CurrentTabIndex = Tabs.IndexOf(tab);
Logger.Trace("SyncTabStatesWithDatabase updated entry for tab '{Title}': {@Entry}", tab.TabTitle, entry);
Logger.Trace(
"SyncTabStatesWithDatabase updated entry for tab '{Title}': {@Entry}",
tab.TabTitle,
entry
);
await liteDbContext.InferenceProjects.UpsertAsync(entry);
}
@ -408,7 +432,10 @@ public partial class InferenceViewModel : PageViewModelBase, IAsyncDisposable
return;
}
await notificationService.TryAsync(ClientManager.CloseAsync(), "Could not disconnect from ComfyUI backend");
await notificationService.TryAsync(
ClientManager.CloseAsync(),
"Could not disconnect from ComfyUI backend"
);
}
/// <summary>
@ -464,7 +491,11 @@ public partial class InferenceViewModel : PageViewModelBase, IAsyncDisposable
await using var stream = await result.OpenWriteAsync();
stream.SetLength(0); // Overwrite fully
await JsonSerializer.SerializeAsync(stream, document, new JsonSerializerOptions { WriteIndented = true });
await JsonSerializer.SerializeAsync(
stream,
document,
new JsonSerializerOptions { WriteIndented = true }
);
}
catch (Exception e)
{
@ -512,7 +543,11 @@ public partial class InferenceViewModel : PageViewModelBase, IAsyncDisposable
await using var stream = projectFile.Info.OpenWrite();
stream.SetLength(0); // Overwrite fully
await JsonSerializer.SerializeAsync(stream, document, new JsonSerializerOptions { WriteIndented = true });
await JsonSerializer.SerializeAsync(
stream,
document,
new JsonSerializerOptions { WriteIndented = true }
);
}
catch (Exception e)
{
@ -624,6 +659,38 @@ public partial class InferenceViewModel : PageViewModelBase, IAsyncDisposable
await SyncTabStatesWithDatabase();
}
private async Task AddImageToImageFromImage(LocalImageFile imageFile)
{
var imgToImgVm = vmFactory.Get<InferenceImageToImageViewModel>();
imgToImgVm.SelectImageCardViewModel.ImageSource = new ImageSource(imageFile.AbsolutePath);
if (imageFile.GenerationParameters != null)
{
imgToImgVm.LoadStateFromParameters(imageFile.GenerationParameters);
}
Tabs.Add(imgToImgVm);
SelectedTab = imgToImgVm;
await SyncTabStatesWithDatabase();
}
private async Task AddImageToVideoFromImage(LocalImageFile imageFile)
{
var imgToVidVm = vmFactory.Get<InferenceImageToVideoViewModel>();
imgToVidVm.SelectImageCardViewModel.ImageSource = new ImageSource(imageFile.AbsolutePath);
if (imageFile.GenerationParameters != null)
{
imgToVidVm.LoadStateFromParameters(imageFile.GenerationParameters);
}
Tabs.Add(imgToVidVm);
SelectedTab = imgToVidVm;
await SyncTabStatesWithDatabase();
}
/// <summary>
/// Menu "Open Project" command.
/// </summary>

12
StabilityMatrix.Avalonia/ViewModels/OutputsPageViewModel.cs

@ -315,6 +315,18 @@ public partial class OutputsPageViewModel : PageViewModelBase
EventManager.Instance.OnInferenceUpscaleRequested(vm.ImageFile);
}
public void SendToImageToImage(OutputImageViewModel vm)
{
navigationService.NavigateTo<InferenceViewModel>();
EventManager.Instance.OnInferenceImageToImageRequested(vm.ImageFile);
}
public void SendToImageToVideo(OutputImageViewModel vm)
{
navigationService.NavigateTo<InferenceViewModel>();
EventManager.Instance.OnInferenceImageToVideoRequested(vm.ImageFile);
}
public void ClearSelection()
{
foreach (var output in Outputs)

16
StabilityMatrix.Avalonia/Views/OutputsPage.axaml

@ -219,19 +219,11 @@
IconSource="FullScreenMaximize"
Text="{x:Static lang:Resources.Label_TextToImage}" />
<ui:MenuFlyoutItem
Command="{Binding $parent[ItemsRepeater].((vm:OutputsPageViewModel)DataContext).SendToImageToImage}"
CommandParameter="{Binding}"
HotKey="{x:Null}"
IconSource="ImageCopy"
IsEnabled="False"
IsVisible="False"
Text="{x:Static lang:Resources.Label_ImageToImage}" />
<ui:MenuFlyoutItem
CommandParameter="{Binding}"
HotKey="{x:Null}"
IconSource="ImageEdit"
IsEnabled="False"
IsVisible="False"
Text="{x:Static lang:Resources.Label_Inpainting}" />
<ui:MenuFlyoutItem
Command="{Binding $parent[ItemsRepeater].((vm:OutputsPageViewModel)DataContext).SendToUpscale}"
CommandParameter="{Binding}"
@ -241,6 +233,12 @@
<fluentAvalonia:SymbolIconSource FontSize="10" Symbol="ResizeImage" />
</ui:MenuFlyoutItem.IconSource>
</ui:MenuFlyoutItem>
<ui:MenuFlyoutItem
Command="{Binding $parent[ItemsRepeater].((vm:OutputsPageViewModel)DataContext).SendToImageToVideo}"
CommandParameter="{Binding}"
HotKey="{x:Null}"
IconSource="Video"
Text="{x:Static lang:Resources.Label_ImageToVideo}" />
</ui:MenuFlyoutSubItem>
</ui:FAMenuFlyout>
</selectableImageCard:SelectableImageButton.ContextFlyout>

23
StabilityMatrix.Core/Helper/EventManager.cs

@ -37,15 +37,14 @@ public class EventManager
public event EventHandler<FilePath>? ImageFileAdded;
public event EventHandler<LocalImageFile>? InferenceTextToImageRequested;
public event EventHandler<LocalImageFile>? InferenceUpscaleRequested;
public event EventHandler<LocalImageFile>? InferenceImageToImageRequested;
public event EventHandler<LocalImageFile>? InferenceImageToVideoRequested;
public void OnGlobalProgressChanged(int progress) =>
GlobalProgressChanged?.Invoke(this, progress);
public void OnGlobalProgressChanged(int progress) => GlobalProgressChanged?.Invoke(this, progress);
public void OnInstalledPackagesChanged() =>
InstalledPackagesChanged?.Invoke(this, EventArgs.Empty);
public void OnInstalledPackagesChanged() => InstalledPackagesChanged?.Invoke(this, EventArgs.Empty);
public void OnOneClickInstallFinished(bool skipped) =>
OneClickInstallFinished?.Invoke(this, skipped);
public void OnOneClickInstallFinished(bool skipped) => OneClickInstallFinished?.Invoke(this, skipped);
public void OnTeachingTooltipNeeded() => TeachingTooltipNeeded?.Invoke(this, EventArgs.Empty);
@ -53,11 +52,9 @@ public class EventManager
public void OnUpdateAvailable(UpdateInfo args) => UpdateAvailable?.Invoke(this, args);
public void OnPackageLaunchRequested(Guid packageId) =>
PackageLaunchRequested?.Invoke(this, packageId);
public void OnPackageLaunchRequested(Guid packageId) => PackageLaunchRequested?.Invoke(this, packageId);
public void OnScrollToBottomRequested() =>
ScrollToBottomRequested?.Invoke(this, EventArgs.Empty);
public void OnScrollToBottomRequested() => ScrollToBottomRequested?.Invoke(this, EventArgs.Empty);
public void OnProgressChanged(ProgressItem progress) => ProgressChanged?.Invoke(this, progress);
@ -83,4 +80,10 @@ public class EventManager
public void OnInferenceUpscaleRequested(LocalImageFile imageFile) =>
InferenceUpscaleRequested?.Invoke(this, imageFile);
public void OnInferenceImageToImageRequested(LocalImageFile imageFile) =>
InferenceImageToImageRequested?.Invoke(this, imageFile);
public void OnInferenceImageToVideoRequested(LocalImageFile imageFile) =>
InferenceImageToVideoRequested?.Invoke(this, imageFile);
}

2
StabilityMatrix.Core/Models/Database/LocalImageFile.cs

@ -83,7 +83,7 @@ public record LocalImageFile
// TODO: Support other types
const LocalImageFileType imageType = LocalImageFileType.Inference | LocalImageFileType.TextToImage;
if (filePath.Extension.Contains("webp"))
if (filePath.Extension.Equals(".webp", StringComparison.OrdinalIgnoreCase))
{
var paramsJson = ImageMetadata.ReadTextChunkFromWebp(
filePath,

Loading…
Cancel
Save