diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 39e3fe37..87c9e984 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,9 +26,10 @@ jobs: run: dotnet restore - name: Build - run: dotnet build --configuration Release --output out --no-restore + run: dotnet publish -o out -c Release --no-restore --self-contained false -p:IncludeNativeLibrariesForSelfExtract=false - name: Upload Artifacts + if: ${{ github.event_name == 'push' }} uses: actions/upload-artifact@v2 with: name: build diff --git a/.github/workflows/remove-old-artifacts.yml b/.github/workflows/remove-old-artifacts.yml new file mode 100644 index 00000000..cb30c304 --- /dev/null +++ b/.github/workflows/remove-old-artifacts.yml @@ -0,0 +1,20 @@ +name: Remove old artifacts + +on: + workflow_dispatch: + schedule: + # Every day at 1am + - cron: '0 1 * * *' + +jobs: + remove-old-artifacts: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Remove old artifacts + uses: c-hive/gha-remove-artifacts@v1 + with: + age: '1 day' + skip-tags: true + skip-recent: 1 diff --git a/StabilityMatrix/Api/IA3WebApi.cs b/StabilityMatrix/Api/IA3WebApi.cs new file mode 100644 index 00000000..6dd9544d --- /dev/null +++ b/StabilityMatrix/Api/IA3WebApi.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; +using Refit; +using StabilityMatrix.Models.Api; + +namespace StabilityMatrix.Api; + +[Headers("User-Agent: StabilityMatrix")] +public interface IA3WebApi +{ + [Get("/internal/ping")] + Task GetPing(); + + [Post("/sdapi/v1/txt2img")] + Task TextToImage([Body] TextToImageRequest request); + + [Get("/sdapi/v1/progress")] + Task GetProgress([Body] ProgressRequest request); +} diff --git a/StabilityMatrix/App.xaml.cs b/StabilityMatrix/App.xaml.cs index 863cfed1..6d108a3a 100644 --- a/StabilityMatrix/App.xaml.cs +++ b/StabilityMatrix/App.xaml.cs @@ -2,6 +2,8 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Text.Json; +using System.Text.Json.Serialization; using System.Windows; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -30,20 +32,37 @@ namespace StabilityMatrix { DispatcherUnhandledException += App_DispatcherUnhandledException; } + var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton(); serviceCollection.AddTransient(); serviceCollection.AddTransient(); serviceCollection.AddTransient(); serviceCollection.AddTransient(); + serviceCollection.AddTransient(); serviceCollection.AddTransient(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + + var jsonOptions = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + }; + var refitSettings = new RefitSettings + { + ContentSerializer = new SystemTextJsonContentSerializer(jsonOptions) + }; + serviceCollection.AddRefitClient(); + serviceCollection.AddRefitClient(refitSettings).ConfigureHttpClient(client => + { + client.BaseAddress = new Uri("http://localhost:7860"); + }); var logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log.txt"); var logConfig = new NLog.Config.LoggingConfiguration(); diff --git a/StabilityMatrix/Helper/AsyncDispatchTimer.cs b/StabilityMatrix/Helper/AsyncDispatchTimer.cs new file mode 100644 index 00000000..f322eb60 --- /dev/null +++ b/StabilityMatrix/Helper/AsyncDispatchTimer.cs @@ -0,0 +1,50 @@ +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using System.Windows.Threading; + +namespace StabilityMatrix.Helper; + +public class AsyncDispatcherTimer : DispatcherTimer +{ + public AsyncDispatcherTimer() + { + Tick += AsyncDispatcherTimer_Tick; + } + + private async void AsyncDispatcherTimer_Tick(object? sender, EventArgs e) + { + if (TickTask == null) + { + // no task to run + return; + } + + if (IsRunning && !IsReentrant) + { + // previous task hasn't completed + return; + } + + try + { + IsRunning = true; + await TickTask.Invoke(); + } + catch (Exception) + { + Debug.WriteLine("Task Failed"); + throw; + } + finally + { + // allow it to run again + IsRunning = false; + } + } + + public bool IsReentrant { get; set; } + public bool IsRunning { get; private set; } + + public Func? TickTask { get; set; } +} diff --git a/StabilityMatrix/MainWindow.xaml b/StabilityMatrix/MainWindow.xaml index 301089e7..2b73df67 100644 --- a/StabilityMatrix/MainWindow.xaml +++ b/StabilityMatrix/MainWindow.xaml @@ -56,6 +56,11 @@ + + + + + diff --git a/StabilityMatrix/Models/Api/ImageResponse.cs b/StabilityMatrix/Models/Api/ImageResponse.cs new file mode 100644 index 00000000..ad62ed10 --- /dev/null +++ b/StabilityMatrix/Models/Api/ImageResponse.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; +using StabilityMatrix.ViewModels; + +namespace StabilityMatrix.Models.Api; + +public class ImageResponse +{ + [JsonPropertyName("images")] + public string[] Images { get; set; } + + [JsonPropertyName("info")] + public string? Info { get; set; } +} diff --git a/StabilityMatrix/Models/Api/ProgressRequest.cs b/StabilityMatrix/Models/Api/ProgressRequest.cs new file mode 100644 index 00000000..e24eba05 --- /dev/null +++ b/StabilityMatrix/Models/Api/ProgressRequest.cs @@ -0,0 +1,9 @@ +using System.Text.Json.Serialization; + +namespace StabilityMatrix.Models.Api; + +public class ProgressRequest +{ + [JsonPropertyName("skip_current_image")] + public bool? SkipCurrentImage { get; set; } +} diff --git a/StabilityMatrix/Models/Api/ProgressResponse.cs b/StabilityMatrix/Models/Api/ProgressResponse.cs new file mode 100644 index 00000000..2f0e1a7c --- /dev/null +++ b/StabilityMatrix/Models/Api/ProgressResponse.cs @@ -0,0 +1,24 @@ +using System.Text.Json.Serialization; + +namespace StabilityMatrix.Models.Api; + +public class ProgressResponse +{ + // Range from 0 to 1 + [JsonPropertyName("progress")] + public float Progress { get; set; } + + // ETA in seconds + [JsonPropertyName("eta_relative")] + public float EtaRelative { get; set; } + + // state: dict + + // The current image in base64 format. opts.show_progress_every_n_steps is required for this to work + [JsonPropertyName("current_image")] + public string? CurrentImage { get; set; } + + [JsonPropertyName("textinfo")] + public string? TextInfo { get; set; } + +} diff --git a/StabilityMatrix/Models/Api/TextToImageRequest.cs b/StabilityMatrix/Models/Api/TextToImageRequest.cs new file mode 100644 index 00000000..ccc6ab0f --- /dev/null +++ b/StabilityMatrix/Models/Api/TextToImageRequest.cs @@ -0,0 +1,134 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace StabilityMatrix.Models.Api; + + +public class TextToImageRequest +{ + [JsonPropertyName("enable_hr")] + public bool? EnableHr { get; set; } + + [JsonPropertyName("denoising_strength")] + public int? DenoisingStrength { get; set; } + + [JsonPropertyName("firstphase_width")] + public int? FirstPhaseWidth { get; set; } + + [JsonPropertyName("firstphase_height")] + public int? FirstPhaseHeight { get; set; } + + [JsonPropertyName("hr_scale")] + public int? HrScale { get; set; } + + [JsonPropertyName("hr_upscaler")] + public string? HrUpscaler { get; set; } + + [JsonPropertyName("hr_second_pass_steps")] + public int? HrSecondPassSteps { get; set; } + + [JsonPropertyName("hr_resize_x")] + public int? HrResizeX { get; set; } + + [JsonPropertyName("hr_resize_y")] + public int? HrResizeY { get; set; } + + [JsonPropertyName("prompt")] + public string Prompt { get; set; } + + [JsonPropertyName("styles")] + public string?[] Styles { get; set; } + + [JsonPropertyName("seed")] + public int? Seed { get; set; } + + [JsonPropertyName("subseed")] + public int? Subseed { get; set; } + + [JsonPropertyName("subseed_strength")] + public int? SubseedStrength { get; set; } + + [JsonPropertyName("seed_resize_from_h")] + public int? SeedResizeFromH { get; set; } + + [JsonPropertyName("seed_resize_from_w")] + public int? SeedResizeFromW { get; set; } + + [JsonPropertyName("sampler_name")] + public string? SamplerName { get; set; } + + [JsonPropertyName("batch_size")] + public int? BatchSize { get; set; } + + [JsonPropertyName("n_iter")] + public int? NIter { get; set; } + + [JsonPropertyName("steps")] + public int? Steps { get; set; } + + [JsonPropertyName("cfg_scale")] + public int? CfgScale { get; set; } + + [JsonPropertyName("width")] + public int? Width { get; set; } + + [JsonPropertyName("height")] + public int? Height { get; set; } + + [JsonPropertyName("restore_faces")] + public bool? RestoreFaces { get; set; } + + [JsonPropertyName("tiling")] + public bool? Tiling { get; set; } + + [JsonPropertyName("do_not_save_samples")] + public bool? DoNotSaveSamples { get; set; } + + [JsonPropertyName("do_not_save_grid")] + public bool? DoNotSaveGrid { get; set; } + + [JsonPropertyName("negative_prompt")] + public string? NegativePrompt { get; set; } + + [JsonPropertyName("eta")] + public int? Eta { get; set; } + + [JsonPropertyName("s_min_uncond")] + public int? SMinUncond { get; set; } + + [JsonPropertyName("s_churn")] + public int? SChurn { get; set; } + + [JsonPropertyName("s_tmax")] + public int? STmax { get; set; } + + [JsonPropertyName("s_tmin")] + public int? STmin { get; set; } + + [JsonPropertyName("s_noise")] + public int? SNoise { get; set; } + + [JsonPropertyName("override_settings")] + public Dictionary? OverrideSettings { get; set; } + + [JsonPropertyName("override_settings_restore_afterwards")] + public bool? OverrideSettingsRestoreAfterwards { get; set; } + + [JsonPropertyName("script_args")] + public string[]? ScriptArgs { get; set; } + + [JsonPropertyName("sampler_index")] + public string? SamplerIndex { get; set; } + + [JsonPropertyName("script_name")] + public string? ScriptName { get; set; } + + [JsonPropertyName("send_images")] + public bool? SendImages { get; set; } + + [JsonPropertyName("save_images")] + public bool? SaveImages { get; set; } + + [JsonPropertyName("alwayson_scripts")] + public Dictionary? AlwaysOnScripts { get; set; } +} diff --git a/StabilityMatrix/SettingsPage.xaml b/StabilityMatrix/SettingsPage.xaml index 66d50e73..d38e9b26 100644 --- a/StabilityMatrix/SettingsPage.xaml +++ b/StabilityMatrix/SettingsPage.xaml @@ -1,65 +1,99 @@ - - + xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" + xmlns:viewModels="clr-namespace:StabilityMatrix.ViewModels" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + + - - + + - - - - - + + + + + - + - - - -