diff --git a/SlipItIn.Server/Data/DbSeeder.cs b/SlipItIn.Server/Data/DbSeeder.cs
new file mode 100644
index 0000000..dc2e38c
--- /dev/null
+++ b/SlipItIn.Server/Data/DbSeeder.cs
@@ -0,0 +1,89 @@
+using Microsoft.EntityFrameworkCore;
+using SlipItIn.Shared.Models;
+
+namespace SlipItIn.Server.Data;
+
+///
+/// Befüllt die Datenbank mit Testdaten (2 Testuser, einige Dutzend Phrasen),
+/// wenn sie leer ist. Dient der Erleichterung manueller Tests.
+///
+public static class DbSeeder
+{
+ public static async Task SeedAsync(SlipItInDbContext context)
+ {
+ // Nur seeden, wenn die Datenbank leer ist
+ if (await context.Users.AnyAsync() || await context.Phrases.AnyAsync())
+ return;
+
+ var alice = new User
+ {
+ Username = "alice",
+ Email = "alice@test.local",
+ PasswordHash = BCrypt.Net.BCrypt.HashPassword("Test123!")
+ };
+
+ var bob = new User
+ {
+ Username = "bob",
+ Email = "bob@test.local",
+ PasswordHash = BCrypt.Net.BCrypt.HashPassword("Test123!")
+ };
+
+ context.Users.AddRange(alice, bob);
+ await context.SaveChangesAsync();
+
+ var phrases = new[]
+ {
+ "Das hat mir meine Oma schon immer gesagt.",
+ "Ich hab da mal eine Doku gesehen.",
+ "Das ist wie damals in der Grundschule.",
+ "Das muss man sich mal auf der Zunge zergehen lassen.",
+ "Da kommt mir direkt ein Lied in den Sinn.",
+ "Das ist wie beim Autofahren: Bremsen kann man immer noch.",
+ "Ich habe das Gefühl, wir reden aneinander vorbei.",
+ "Das würde ich an deiner Stelle nochmal überdenken.",
+ "Ich glaube, da steckt mehr dahinter.",
+ "Also ich finde, das riecht verdächtig nach Montag.",
+ "Das schmeckt nach mehr.",
+ "Da ist der Wurm drin.",
+ "Das hat hand und Fuß.",
+ "Das ist ein zweischneidiges Schwert.",
+ "Da liegt der Hase im Pfeffer.",
+ "Das ist wie ein guter Wein – wird mit den Jahren besser.",
+ "Ich würde sagen: Glück im Unglück.",
+ "Das ist schon fast eine Wissenschaft für sich.",
+ "Man muss das Kind beim Namen nennen.",
+ "Das ist wie Weihnachten und Geburtstag zusammen.",
+ "Da geht mir das Herz auf.",
+ "Ich würde das jetzt nicht überbewerten.",
+ "Das kommt mir spanisch vor.",
+ "Das ist das Beste seit geschnittenem Brot.",
+ "Da bleibt kein Auge trocken.",
+ "Das ist wie Nägel mit Köpfen machen.",
+ "Ich habe da so eine Vermutung.",
+ "Das ist wie ein roter Faden.",
+ "Da platzt mir gleich der Kragen.",
+ "Ich bin da ganz bei dir.",
+ "Das muss man erstmal sacken lassen.",
+ "Das ist wie ein offenes Buch.",
+ "Da würde ich nicht drauf wetten.",
+ "Das ist wie eine Achterbahn der Gefühle.",
+ "Ich hab da ein ganz mieses Gefühl bei.",
+ "Das ist wie ein Dorn im Auge."
+ };
+
+ var random = new Random(42);
+ var creators = new[] { alice, bob };
+
+ foreach (var text in phrases)
+ {
+ context.Phrases.Add(new Phrase
+ {
+ Text = text,
+ CreatorId = creators[random.Next(creators.Length)].Id
+ });
+ }
+
+ await context.SaveChangesAsync();
+ }
+}
diff --git a/SlipItIn.Server/Program.cs b/SlipItIn.Server/Program.cs
index 55a9cc0..fa5f097 100644
--- a/SlipItIn.Server/Program.cs
+++ b/SlipItIn.Server/Program.cs
@@ -98,21 +98,28 @@ var app = builder.Build();
// Aspire Default Endpoints (Health Checks)
app.MapDefaultEndpoints();
-// Migrations anwenden
+// Migrations anwenden und Testdaten seeden (nur wenn die Datenbank leer ist)
using (var scope = app.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService();
db.Database.Migrate();
+ await DbSeeder.SeedAsync(db);
}
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
- app.UseCors("AllowAll");
}
-app.UseHttpsRedirection();
+app.UseCors("AllowAll");
+
+// Beim Emulator/geräteübergreifenden Zugriff würde die HTTPS-Umleitung
+// den Client auf eine nicht vertrauenswürdige Dev-Zertifikats-URL schicken.
+if (!app.Environment.IsDevelopment())
+{
+ app.UseHttpsRedirection();
+}
app.UseAuthentication();
app.UseAuthorization();
diff --git a/SlipItIn/Platforms/Android/AndroidManifest.Debug.xml b/SlipItIn/Platforms/Android/AndroidManifest.Debug.xml
new file mode 100644
index 0000000..9bb68cf
--- /dev/null
+++ b/SlipItIn/Platforms/Android/AndroidManifest.Debug.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SlipItIn/Platforms/Android/AndroidManifest.Release.xml b/SlipItIn/Platforms/Android/AndroidManifest.Release.xml
new file mode 100644
index 0000000..2b26593
--- /dev/null
+++ b/SlipItIn/Platforms/Android/AndroidManifest.Release.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SlipItIn/Platforms/Android/AndroidManifest.xml b/SlipItIn/Platforms/Android/AndroidManifest.xml
deleted file mode 100644
index 60ca4c2..0000000
--- a/SlipItIn/Platforms/Android/AndroidManifest.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/SlipItIn/Services/AppConfigurationService.cs b/SlipItIn/Services/AppConfigurationService.cs
index 8a57d94..eea0248 100644
--- a/SlipItIn/Services/AppConfigurationService.cs
+++ b/SlipItIn/Services/AppConfigurationService.cs
@@ -4,9 +4,20 @@ namespace SlipItIn.Services;
public class AppConfigurationService : IAppConfigurationService
{
+ private const string ApiBaseUrlPreferenceKey = "api_base_url";
private const string DefaultApiBaseUrl = "https://localhost:7274";
+ private const string AndroidEmulatorApiBaseUrl = "http://10.0.2.2:5234";
- public string ApiBaseUrl => DefaultApiBaseUrl;
+ public string ApiBaseUrl => Preferences.Default
+ .Get(ApiBaseUrlPreferenceKey, GetPlatformDefaultApiBaseUrl())
+ .TrimEnd('/');
- public string HubUrl => $"{DefaultApiBaseUrl.TrimEnd('/')}/hubs/game";
+ public string HubUrl => $"{ApiBaseUrl}/hubs/game";
+
+ private static string GetPlatformDefaultApiBaseUrl()
+ {
+ return DeviceInfo.Platform == DevicePlatform.Android
+ ? AndroidEmulatorApiBaseUrl
+ : DefaultApiBaseUrl;
+ }
}
diff --git a/SlipItIn/SlipItIn.csproj b/SlipItIn/SlipItIn.csproj
index 81b956c..27c5b59 100644
--- a/SlipItIn/SlipItIn.csproj
+++ b/SlipItIn/SlipItIn.csproj
@@ -124,4 +124,12 @@
+
+ Platforms\Android\AndroidManifest.Debug.xml
+
+
+
+ Platforms\Android\AndroidManifest.Release.xml
+
+