feat: implement identity authentication, authorization policies, and MAUI platform support with Docker orchestration
This commit is contained in:
@@ -9,41 +9,44 @@ public static class MauiProgram
|
||||
{
|
||||
public static MauiApp CreateMauiApp()
|
||||
{
|
||||
var builder = MauiApp.CreateBuilder();
|
||||
builder
|
||||
.UseMauiApp<App>()
|
||||
.ConfigureFonts(fonts =>
|
||||
{
|
||||
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
|
||||
});
|
||||
try
|
||||
{
|
||||
var builder = MauiApp.CreateBuilder();
|
||||
builder
|
||||
.UseMauiApp<App>();
|
||||
|
||||
builder.Services.AddMauiBlazorWebView();
|
||||
builder.Services.AddMauiBlazorWebView();
|
||||
|
||||
#if DEBUG
|
||||
builder.Services.AddBlazorWebViewDeveloperTools();
|
||||
builder.Logging.AddDebug();
|
||||
builder.Services.AddBlazorWebViewDeveloperTools();
|
||||
builder.Logging.AddDebug();
|
||||
#endif
|
||||
|
||||
// Infrastructure
|
||||
builder.Services.AddSingleton<IPlatformService, MauiPlatformService>();
|
||||
builder.Services.AddSingleton<INativeStorageService, MauiStorageService>();
|
||||
|
||||
// Identity
|
||||
builder.Services.AddScoped<IIdentityService, IdentityService>();
|
||||
builder.Services.AddScoped<NexusAuthenticationStateProvider>();
|
||||
builder.Services.AddScoped<Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider>(sp =>
|
||||
sp.GetRequiredService<NexusAuthenticationStateProvider>());
|
||||
builder.Services.AddCascadingAuthenticationState();
|
||||
builder.Services.AddAuthorizationCore();
|
||||
// Minimal Infrastructure
|
||||
builder.Services.AddSingleton<IPlatformService, MauiPlatformService>();
|
||||
builder.Services.AddSingleton<INativeStorageService, MauiStorageService>();
|
||||
|
||||
// Minimal Identity (Safe Mode)
|
||||
builder.Services.AddScoped<NexusAuthenticationStateProvider>();
|
||||
builder.Services.AddScoped<Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider>(sp =>
|
||||
sp.GetRequiredService<NexusAuthenticationStateProvider>());
|
||||
builder.Services.AddAuthorizationCore();
|
||||
|
||||
// Network
|
||||
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("http://localhost:5000") }); // Update with real API URL later
|
||||
// Basic Network
|
||||
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("http://10.0.2.2:5000") });
|
||||
|
||||
// Shared UI State
|
||||
builder.Services.AddScoped<IThemeService, ThemeService>();
|
||||
builder.Services.AddScoped<IFocusModeService, FocusModeService>();
|
||||
builder.Services.AddScoped<IQuizStateService, QuizStateService>();
|
||||
// UI State
|
||||
builder.Services.AddScoped<IThemeService, ThemeService>();
|
||||
builder.Services.AddScoped<IFocusModeService, FocusModeService>();
|
||||
builder.Services.AddScoped<IQuizStateService, QuizStateService>();
|
||||
|
||||
return builder.Build();
|
||||
return builder.Build();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// This might help the debugger catch the exception more reliably
|
||||
System.Diagnostics.Debug.WriteLine($"MAUI Startup Error: {ex}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.nexus.ereader">
|
||||
<application android:allowBackup="true" android:supportsRtl="true"></application>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
||||
@@ -0,0 +1,19 @@
|
||||
using Android.App;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
using Android.Util;
|
||||
|
||||
namespace NexusReader.Maui;
|
||||
|
||||
[Activity(Theme = "@style/Maui.MainTheme.NoActionBar", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
|
||||
public class MainActivity : MauiAppCompatActivity
|
||||
{
|
||||
private const string Tag = "NEXUS_MAUI";
|
||||
|
||||
protected override void OnCreate(Bundle? savedInstanceState)
|
||||
{
|
||||
Log.Debug(Tag, "MainActivity.OnCreate starting...");
|
||||
base.OnCreate(savedInstanceState);
|
||||
Log.Debug(Tag, "MainActivity.OnCreate completed");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Android.App;
|
||||
using Android.Runtime;
|
||||
using Android.Util;
|
||||
|
||||
namespace NexusReader.Maui;
|
||||
|
||||
[Application]
|
||||
public class MainApplication : MauiApplication
|
||||
{
|
||||
private const string Tag = "NEXUS_MAUI";
|
||||
|
||||
public MainApplication(IntPtr handle, JniHandleOwnership ownership)
|
||||
: base(handle, ownership)
|
||||
{
|
||||
Log.Debug(Tag, "MainApplication constructor called");
|
||||
}
|
||||
|
||||
protected override MauiApp CreateMauiApp()
|
||||
{
|
||||
Log.Debug(Tag, "CreateMauiApp starting...");
|
||||
try
|
||||
{
|
||||
var app = MauiProgram.CreateMauiApp();
|
||||
Log.Debug(Tag, "CreateMauiApp successful");
|
||||
return app;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(Tag, $"CreateMauiApp FAILED: {ex.Message}");
|
||||
Log.Error(Tag, ex.StackTrace);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#512BD4</color>
|
||||
<color name="colorPrimaryDark">#2B0B98</color>
|
||||
<color name="colorAccent">#DFD8F7</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<resources>
|
||||
<style name="Maui.MainTheme.NoActionBar" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<item name="android:windowTranslucentStatus">true</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowActionBar">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<Style TargetType="Label">
|
||||
<Setter Property="TextColor" Value="{StaticResource Gray100}" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<!-- <Setter Property="FontFamily" Value="OpenSansRegular" /> -->
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
</Style>
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
using FluentResults;
|
||||
using Microsoft.Maui.Storage;
|
||||
using NexusReader.Application.Abstractions.Services;
|
||||
|
||||
namespace NexusReader.Maui.Services;
|
||||
|
||||
public class MauiStorageService : INativeStorageService
|
||||
{
|
||||
public Result SaveString(string key, string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
Preferences.Default.Set(key, value);
|
||||
return Result.Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public Result<string?> GetString(string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Result.Ok(Preferences.Default.Get<string?>(key, null));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public Result SaveBool(string key, bool value)
|
||||
{
|
||||
try
|
||||
{
|
||||
Preferences.Default.Set(key, value);
|
||||
return Result.Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public Result<bool> GetBool(string key, bool defaultValue = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Result.Ok(Preferences.Default.Get(key, defaultValue));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public Result Remove(string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
Preferences.Default.Remove(key);
|
||||
return Result.Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result> SaveSecureString(string key, string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
await SecureStorage.Default.SetAsync(key, value);
|
||||
return Result.Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result<string?>> GetSecureString(string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
var value = await SecureStorage.Default.GetAsync(key);
|
||||
return Result.Ok(value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public Result RemoveSecure(string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
SecureStorage.Default.Remove(key);
|
||||
return Result.Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user