diff --git a/src/AltGen.API/Program.cs b/src/AltGen.API/Program.cs
index 6caf5b4..742d76c 100644
--- a/src/AltGen.API/Program.cs
+++ b/src/AltGen.API/Program.cs
@@ -45,6 +45,21 @@ builder.Services.AddRateLimiter(
}
);
+// TODO: Make CORS more restrictive
+// only allow requests from the web
+// client
+const string corsPolicyName = "cors";
+
+builder.Services.AddCors(o =>
+{
+ o.AddPolicy(corsPolicyName, p =>
+ {
+ p.AllowAnyOrigin()
+ .AllowAnyOrigin()
+ .AllowAnyMethod();
+ });
+});
+
var app = builder.Build();
if (app.Environment.IsDevelopment())
@@ -57,6 +72,8 @@ if (app.Environment.IsProduction())
app.UseRateLimiter();
}
+app.UseCors(corsPolicyName);
+
app.UseHttpsRedirection();
app.UseStatusCodePages();
diff --git a/src/AltGen.Console/Generate/AltGenService.cs b/src/AltGen.Console/Generate/AltGenService.cs
index f782c7c..7b5802f 100644
--- a/src/AltGen.Console/Generate/AltGenService.cs
+++ b/src/AltGen.Console/Generate/AltGenService.cs
@@ -1,5 +1,6 @@
namespace AltGen.Console.Generate;
+// TODO: Use shared library version of this service
sealed class AltGenService(HttpClient client) : IAltGenService
{
static readonly JsonSerializerOptions JsonOptions = new()
diff --git a/src/AltGen.Shared/AltGen.Shared.csproj b/src/AltGen.Shared/AltGen.Shared.csproj
new file mode 100644
index 0000000..125f4c9
--- /dev/null
+++ b/src/AltGen.Shared/AltGen.Shared.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net9.0
+ enable
+ enable
+
+
+
diff --git a/src/AltGen.Shared/Generate/AltGenService.cs b/src/AltGen.Shared/Generate/AltGenService.cs
new file mode 100644
index 0000000..bfd773d
--- /dev/null
+++ b/src/AltGen.Shared/Generate/AltGenService.cs
@@ -0,0 +1,47 @@
+using System.Net.Http.Headers;
+using System.Text.Json;
+
+namespace AltGen.Shared.Generate;
+
+public sealed class AltGenService(HttpClient client) : IAltGenService
+{
+ static readonly JsonSerializerOptions JsonOptions = new()
+ {
+ PropertyNameCaseInsensitive = true
+ };
+ readonly HttpClient _client = client;
+
+ public async Task GenerateAltTextAsync(GenerateAltTextRequest req)
+ {
+ var byteContent = new ByteArrayContent(req.Image);
+ byteContent.Headers.ContentType = new MediaTypeHeaderValue(req.ContentType);
+
+ var request = new HttpRequestMessage(HttpMethod.Post, "/generate")
+ {
+ Content = new MultipartFormDataContent
+ {
+ { new StringContent(req.Provider), "provider" },
+ { new StringContent(req.ProviderKey), "providerKey" },
+ { byteContent, "file", req.FileName }
+ }
+ };
+
+ var response = await _client.SendAsync(request);
+ var content = await response.Content.ReadAsStringAsync();
+
+ if (response.IsSuccessStatusCode is false)
+ {
+ throw new AltTextException("Failed to generate alt text.");
+ }
+
+ var altTextResponse = JsonSerializer.Deserialize(content, JsonOptions) ?? throw new AltTextException("Failed to deserialize response.");
+
+ return altTextResponse.AltText;
+ }
+}
+
+record AltTextResponse(string AltText);
+
+class AltTextException(string message) : Exception(message)
+{
+}
\ No newline at end of file
diff --git a/src/AltGen.Shared/Generate/GenerateAltTextRequest.cs b/src/AltGen.Shared/Generate/GenerateAltTextRequest.cs
new file mode 100644
index 0000000..a0d24b4
--- /dev/null
+++ b/src/AltGen.Shared/Generate/GenerateAltTextRequest.cs
@@ -0,0 +1,9 @@
+namespace AltGen.Shared.Generate;
+
+public record GenerateAltTextRequest(
+ string Provider,
+ string ProviderKey,
+ string FileName,
+ byte[] Image,
+ string ContentType
+);
diff --git a/src/AltGen.Shared/Generate/IAltGenService.cs b/src/AltGen.Shared/Generate/IAltGenService.cs
new file mode 100644
index 0000000..0a1a593
--- /dev/null
+++ b/src/AltGen.Shared/Generate/IAltGenService.cs
@@ -0,0 +1,6 @@
+namespace AltGen.Shared.Generate;
+
+public interface IAltGenService
+{
+ public Task GenerateAltTextAsync(GenerateAltTextRequest req);
+}
\ No newline at end of file
diff --git a/src/AltGen.Web.Client/AltGen.Web.Client.csproj b/src/AltGen.Web.Client/AltGen.Web.Client.csproj
index c2ddab3..adeed6c 100644
--- a/src/AltGen.Web.Client/AltGen.Web.Client.csproj
+++ b/src/AltGen.Web.Client/AltGen.Web.Client.csproj
@@ -10,6 +10,11 @@
+
+
+
+
+
diff --git a/src/AltGen.Web.Client/Components/Pages/Home.razor b/src/AltGen.Web.Client/Components/Pages/Home.razor
index b04083a..7643028 100644
--- a/src/AltGen.Web.Client/Components/Pages/Home.razor
+++ b/src/AltGen.Web.Client/Components/Pages/Home.razor
@@ -1,24 +1,51 @@
-@inject ILogger Logger
+@using AltGen.Shared.Generate
+@inject ILogger Logger
+@inject IAltGenService AltGenService
@page "/"
-@rendermode InteractiveWebAssembly
+@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
AltGen.Web
AI Generated Alt Text
@code {
- private void LoadFiles(InputFileChangeEventArgs e)
+ private string? _provider;
+ private string? _providerKey;
+
+ private async Task HandleFileChange(InputFileChangeEventArgs e)
{
- var files = e.GetMultipleFiles(5);
-
- foreach (var file in files)
+ var file = e.File;
+
+ if (_provider is null || _providerKey is null || file is null)
{
- Logger.LogInformation("File loaded: {Name}, Size: {Size}", file.Name, file.Size);
+ return;
}
+
+ var fileBytes = new byte[file.Size];
+ using var stream = file.OpenReadStream();
+ await stream.ReadAsync(fileBytes, 0, (int)file.Size);
+
+ var altText = await AltGenService.GenerateAltTextAsync(new(
+ _provider,
+ _providerKey,
+ file.Name,
+ fileBytes,
+ file.ContentType
+ ));
+
+ // TODO: Present on the screen to the user
+ Logger.LogInformation(altText);
}
-}
\ No newline at end of file
+}
diff --git a/src/AltGen.Web.Client/Program.cs b/src/AltGen.Web.Client/Program.cs
index 519269f..5f7cdd1 100644
--- a/src/AltGen.Web.Client/Program.cs
+++ b/src/AltGen.Web.Client/Program.cs
@@ -1,5 +1,10 @@
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
+using AltGen.Shared.Generate;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
+// TODO: Read base url
+// from configuration
+builder.Services.AddHttpClient(c => c.BaseAddress = new("https://localhost:7297"));
+
await builder.Build().RunAsync();
diff --git a/src/AltGen.Web/AltGen.Web.csproj b/src/AltGen.Web/AltGen.Web.csproj
index 469ac5c..345882e 100644
--- a/src/AltGen.Web/AltGen.Web.csproj
+++ b/src/AltGen.Web/AltGen.Web.csproj
@@ -11,4 +11,8 @@
+
+
+
+
diff --git a/src/AltGen.sln b/src/AltGen.sln
index 6bafee2..b9fb0f9 100644
--- a/src/AltGen.sln
+++ b/src/AltGen.sln
@@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AltGen.Web", "AltGen.Web\Al
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AltGen.Web.Client", "AltGen.Web.Client\AltGen.Web.Client.csproj", "{DCE07E79-23A4-490E-A796-EA140D2040C1}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AltGen.Shared", "AltGen.Shared\AltGen.Shared.csproj", "{68D4BC5D-A6FE-41CF-B744-1DB83CCFBC89}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -48,5 +50,9 @@ Global
{DCE07E79-23A4-490E-A796-EA140D2040C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DCE07E79-23A4-490E-A796-EA140D2040C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DCE07E79-23A4-490E-A796-EA140D2040C1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {68D4BC5D-A6FE-41CF-B744-1DB83CCFBC89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {68D4BC5D-A6FE-41CF-B744-1DB83CCFBC89}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {68D4BC5D-A6FE-41CF-B744-1DB83CCFBC89}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {68D4BC5D-A6FE-41CF-B744-1DB83CCFBC89}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal