From 1630bde1eead5d49ac2f9369b7a7062addcbb343 Mon Sep 17 00:00:00 2001 From: sysadmin Date: Tue, 9 Jun 2026 03:03:13 +0100 Subject: [PATCH] feat(welcome): wizard steps + flavour selection UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six wizard step components (Welcome/Flavour/Account/Prefs/Apply/Done), Routes.razor wizard host with Next/Back navigation and IFlavourLoader wiring, bUnit FlavourStepTests (TDD red→green), AccountStep field validation (username/password/admin-password required; BitLocker PIN numeric ≥6 digits). Test project upgraded to Razor SDK / net9.0-windows10.0.19041.0 + UseMaui=true to reference the MAUI app assembly. Non-Windows platform folders removed; demo pages removed. All 14 tests pass (13 existing + 1 new bUnit). Co-Authored-By: Claude Sonnet 4.6 --- .../Components/Pages/Counter.razor | 16 --- .../Components/Pages/Weather.razor | 61 --------- .../Components/Routes.razor | 124 +++++++++++++++++- .../Components/Steps/AccountStep.razor | 84 ++++++++++++ .../Components/Steps/ApplyStep.razor | 16 +++ .../Components/Steps/DoneStep.razor | 14 ++ .../Components/Steps/FlavourStep.razor | 31 +++++ .../Components/Steps/PrefsStep.razor | 30 +++++ .../Components/Steps/WelcomeStep.razor | 13 ++ .../Components/WizardState.cs | 5 + .../Components/_Imports.razor | 2 + .../Platforms/Android/AndroidManifest.xml | 6 - .../Platforms/Android/MainActivity.cs | 10 -- .../Platforms/Android/MainApplication.cs | 15 --- .../Android/Resources/values/colors.xml | 6 - .../Platforms/MacCatalyst/AppDelegate.cs | 9 -- .../Platforms/MacCatalyst/Entitlements.plist | 14 -- .../Platforms/MacCatalyst/Info.plist | 38 ------ .../Platforms/MacCatalyst/Program.cs | 15 --- .../Platforms/Tizen/Main.cs | 16 --- .../Platforms/Tizen/tizen-manifest.xml | 15 --- .../Platforms/iOS/AppDelegate.cs | 9 -- .../Platforms/iOS/Info.plist | 32 ----- .../Platforms/iOS/Program.cs | 15 --- .../iOS/Resources/PrivacyInfo.xcprivacy | 51 ------- .../FlavourStepTests.cs | 23 ++++ .../SilverOS.Welcome.Tests.csproj | 12 +- 27 files changed, 345 insertions(+), 337 deletions(-) delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Components/Pages/Counter.razor delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Components/Pages/Weather.razor create mode 100644 windows/welcome/src/SilverOS.Welcome.App/Components/Steps/AccountStep.razor create mode 100644 windows/welcome/src/SilverOS.Welcome.App/Components/Steps/ApplyStep.razor create mode 100644 windows/welcome/src/SilverOS.Welcome.App/Components/Steps/DoneStep.razor create mode 100644 windows/welcome/src/SilverOS.Welcome.App/Components/Steps/FlavourStep.razor create mode 100644 windows/welcome/src/SilverOS.Welcome.App/Components/Steps/PrefsStep.razor create mode 100644 windows/welcome/src/SilverOS.Welcome.App/Components/Steps/WelcomeStep.razor delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/AndroidManifest.xml delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/MainActivity.cs delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/MainApplication.cs delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/Resources/values/colors.xml delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/AppDelegate.cs delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/Entitlements.plist delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/Info.plist delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/Program.cs delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/Tizen/Main.cs delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/Tizen/tizen-manifest.xml delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/AppDelegate.cs delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/Info.plist delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/Program.cs delete mode 100644 windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/Resources/PrivacyInfo.xcprivacy create mode 100644 windows/welcome/tests/SilverOS.Welcome.Tests/FlavourStepTests.cs diff --git a/windows/welcome/src/SilverOS.Welcome.App/Components/Pages/Counter.razor b/windows/welcome/src/SilverOS.Welcome.App/Components/Pages/Counter.razor deleted file mode 100644 index 6324ad0..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Components/Pages/Counter.razor +++ /dev/null @@ -1,16 +0,0 @@ -@page "/counter" - -

Counter

- -

Current count: @currentCount

- - - -@code { - private int currentCount = 0; - - private void IncrementCount() - { - currentCount++; - } -} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Components/Pages/Weather.razor b/windows/welcome/src/SilverOS.Welcome.App/Components/Pages/Weather.razor deleted file mode 100644 index 472bb98..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Components/Pages/Weather.razor +++ /dev/null @@ -1,61 +0,0 @@ -@page "/weather" - -

Weather

- -

This component demonstrates showing data.

- -@if (forecasts == null) -{ -

Loading...

-} -else -{ - - - - - - - - - - - @foreach (var forecast in forecasts) - { - - - - - - - } - -
DateTemp. (C)Temp. (F)Summary
@forecast.Date.ToShortDateString()@forecast.TemperatureC@forecast.TemperatureF@forecast.Summary
-} - -@code { - private WeatherForecast[]? forecasts; - - protected override async Task OnInitializedAsync() - { - // Simulate asynchronous loading to demonstrate a loading indicator - await Task.Delay(500); - - var startDate = DateOnly.FromDateTime(DateTime.Now); - var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; - forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = startDate.AddDays(index), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = summaries[Random.Shared.Next(summaries.Length)] - }).ToArray(); - } - - private class WeatherForecast - { - public DateOnly Date { get; set; } - public int TemperatureC { get; set; } - public string? Summary { get; set; } - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - } -} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Components/Routes.razor b/windows/welcome/src/SilverOS.Welcome.App/Components/Routes.razor index 631cf80..7100db6 100644 --- a/windows/welcome/src/SilverOS.Welcome.App/Components/Routes.razor +++ b/windows/welcome/src/SilverOS.Welcome.App/Components/Routes.razor @@ -1,6 +1,118 @@ - - - - - - +@using SilverOS.Welcome.App.Components.Steps +@using SilverOS.Welcome.Core.Flavours +@inject IFlavourLoader FlavourLoader +@inject WizardState State + +
+
+
+ @for (int i = 0; i < _stepTitles.Length; i++) + { + var idx = i; + + @_stepTitles[idx] + + } +
+
+ +
+ @if (_loading) + { +

Loading flavours…

+ } + else if (_error is not null) + { +

@_error

+ } + else + { + @switch (_currentStep) + { + case 0: + + break; + case 1: + + break; + case 2: + + break; + case 3: + + break; + case 4: + + break; + case 5: + + break; + } + } +
+ + +
+ +@code { + private static readonly string[] _stepTitles = { "Welcome", "Flavour", "Account", "Prefs", "Apply", "Done" }; + + // Flavours dir: baked alongside the exe at publish time. + private static readonly string FlavoursDir = Path.Combine( + AppContext.BaseDirectory, "flavours"); + + private int _currentStep = 0; + private bool _loading = true; + private string? _error; + private IReadOnlyList _flavours = Array.Empty(); + private AccountStep? _accountStep; + + private bool CanGoNext => _currentStep switch + { + 2 => _accountStep?.IsValid ?? false, + _ => true + }; + + protected override Task OnInitializedAsync() + { + try + { + _flavours = FlavourLoader.Load(FlavoursDir); + } + catch (Exception ex) + { + _error = $"Failed to load flavours: {ex.Message}"; + } + finally + { + _loading = false; + } + return Task.CompletedTask; + } + + void Next() + { + if (_currentStep < _stepTitles.Length - 1) + _currentStep++; + } + + void Back() + { + if (_currentStep > 0) + _currentStep--; + } +} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/AccountStep.razor b/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/AccountStep.razor new file mode 100644 index 0000000..d6676f8 --- /dev/null +++ b/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/AccountStep.razor @@ -0,0 +1,84 @@ +@inject WizardState State + + + +@code { + private readonly Dictionary _errors = new(); + + /// True when all fields are valid. Used by the wizard host to gate Next. + public bool IsValid { get; private set; } + + protected override void OnInitialized() => Validate(); + + private void OnUsernameInput(ChangeEventArgs e) { State.Username = e.Value?.ToString() ?? ""; Validate(); } + private void OnPasswordInput(ChangeEventArgs e) { State.Password = e.Value?.ToString() ?? ""; Validate(); } + private void OnAdminPasswordInput(ChangeEventArgs e) { State.AdminPassword = e.Value?.ToString() ?? ""; Validate(); } + private void OnPinInput(ChangeEventArgs e) { State.BitLockerPin = e.Value?.ToString() ?? ""; Validate(); } + + void Validate() + { + _errors.Clear(); + + if (string.IsNullOrWhiteSpace(State.Username)) + _errors["username"] = "Daily username is required."; + + if (string.IsNullOrWhiteSpace(State.Password)) + _errors["password"] = "Password is required."; + + if (string.IsNullOrWhiteSpace(State.AdminPassword)) + _errors["adminpassword"] = "Administrator password is required."; + + var pin = State.BitLockerPin ?? ""; + if (!System.Text.RegularExpressions.Regex.IsMatch(pin, @"^\d{6,}$")) + _errors["bitlockerpin"] = "BitLocker PIN must be all digits and at least 6 digits long."; + + IsValid = _errors.Count == 0; + } +} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/ApplyStep.razor b/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/ApplyStep.razor new file mode 100644 index 0000000..19ba43d --- /dev/null +++ b/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/ApplyStep.razor @@ -0,0 +1,16 @@ +@* Minimal placeholder — full wiring in Task 11 *@ +
+

Applying Configuration

+

Your settings will be applied now.

+ + @if (_started) + { +

Working… please wait.

+ } +
+ +@code { + private bool _started; + + void Start() => _started = true; +} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/DoneStep.razor b/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/DoneStep.razor new file mode 100644 index 0000000..a42f027 --- /dev/null +++ b/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/DoneStep.razor @@ -0,0 +1,14 @@ +@inject SilverOS.Welcome.Core.Apply.IProcessRunner ProcessRunner + +
+

All Done!

+

Your SilverOS device is configured and ready. Click below to restart and start using it.

+ +
+ +@code { + private async Task RestartNow() + { + await ProcessRunner.RunAsync("cmd.exe", "/c shutdown /r /t 5", CancellationToken.None); + } +} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/FlavourStep.razor b/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/FlavourStep.razor new file mode 100644 index 0000000..18a893f --- /dev/null +++ b/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/FlavourStep.razor @@ -0,0 +1,31 @@ +@inject WizardState State + +
+

What's this device for?

+

Choose the flavour that best matches how this PC will be used.

+
+ @foreach (var f in Flavours) + { +
+

@f.Label

+

@f.Description

+
+ } +
+
+ +@code { + [Parameter] public IReadOnlyList Flavours { get; set; } = Array.Empty(); + + protected override void OnInitialized() + { + State.Flavour ??= Flavours.FirstOrDefault(f => f.IsDefault); + } + + void Select(FlavourManifest f) + { + State.Flavour = f; + } +} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/PrefsStep.razor b/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/PrefsStep.razor new file mode 100644 index 0000000..363cdb2 --- /dev/null +++ b/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/PrefsStep.razor @@ -0,0 +1,30 @@ +@inject WizardState State + +
+

Preferences

+

A few final settings before we apply your configuration.

+ +
+
+ +
+
+ +
+
+ +
+
+
+ +@code { +} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/WelcomeStep.razor b/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/WelcomeStep.razor new file mode 100644 index 0000000..1ef46cc --- /dev/null +++ b/windows/welcome/src/SilverOS.Welcome.App/Components/Steps/WelcomeStep.razor @@ -0,0 +1,13 @@ +@inject WizardState State + +
+
+

Welcome to SilverOS

+

Let's get your device set up the way you want it.

+

This wizard will guide you through a few quick steps to configure your system, create your account, and apply the right security settings for your needs.

+

Takes about 5 minutes.

+
+
+ +@code { +} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Components/WizardState.cs b/windows/welcome/src/SilverOS.Welcome.App/Components/WizardState.cs index 135583e..04b08fd 100644 --- a/windows/welcome/src/SilverOS.Welcome.App/Components/WizardState.cs +++ b/windows/welcome/src/SilverOS.Welcome.App/Components/WizardState.cs @@ -9,4 +9,9 @@ public sealed class WizardState public string Password { get; set; } = ""; public string AdminPassword { get; set; } = ""; public string BitLockerPin { get; set; } = ""; + + // Prefs step + public bool AutoUpdates { get; set; } = true; + public bool Telemetry { get; set; } = false; + public bool InstallDefenderUpdates { get; set; } = true; } diff --git a/windows/welcome/src/SilverOS.Welcome.App/Components/_Imports.razor b/windows/welcome/src/SilverOS.Welcome.App/Components/_Imports.razor index 61d5ca1..8c75f01 100644 --- a/windows/welcome/src/SilverOS.Welcome.App/Components/_Imports.razor +++ b/windows/welcome/src/SilverOS.Welcome.App/Components/_Imports.razor @@ -7,3 +7,5 @@ @using Microsoft.JSInterop @using SilverOS.Welcome.App @using SilverOS.Welcome.App.Components +@using SilverOS.Welcome.App.Components.Steps +@using SilverOS.Welcome.Core.Flavours diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/AndroidManifest.xml b/windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/AndroidManifest.xml deleted file mode 100644 index dbf9e7e..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/AndroidManifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/MainActivity.cs b/windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/MainActivity.cs deleted file mode 100644 index a59d1f0..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/MainActivity.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Android.App; -using Android.Content.PM; -using Android.OS; - -namespace SilverOS.Welcome.App; - -[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] -public class MainActivity : MauiAppCompatActivity -{ -} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/MainApplication.cs b/windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/MainApplication.cs deleted file mode 100644 index 97746f4..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/MainApplication.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Android.App; -using Android.Runtime; - -namespace SilverOS.Welcome.App; - -[Application] -public class MainApplication : MauiApplication -{ - public MainApplication(IntPtr handle, JniHandleOwnership ownership) - : base(handle, ownership) - { - } - - protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); -} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/Resources/values/colors.xml b/windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/Resources/values/colors.xml deleted file mode 100644 index c04d749..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/Android/Resources/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #512BD4 - #2B0B98 - #2B0B98 - \ No newline at end of file diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/AppDelegate.cs b/windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/AppDelegate.cs deleted file mode 100644 index d1f3709..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/AppDelegate.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Foundation; - -namespace SilverOS.Welcome.App; - -[Register("AppDelegate")] -public class AppDelegate : MauiUIApplicationDelegate -{ - protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); -} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/Entitlements.plist b/windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/Entitlements.plist deleted file mode 100644 index de4adc9..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/Entitlements.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - com.apple.security.app-sandbox - - - com.apple.security.network.client - - - - diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/Info.plist b/windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/Info.plist deleted file mode 100644 index 7b1e6e6..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/Info.plist +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - UIDeviceFamily - - 2 - - UIRequiredDeviceCapabilities - - arm64 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - XSAppIconAssets - Assets.xcassets/appicon.appiconset - - diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/Program.cs b/windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/Program.cs deleted file mode 100644 index 8d9f343..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/MacCatalyst/Program.cs +++ /dev/null @@ -1,15 +0,0 @@ -using ObjCRuntime; -using UIKit; - -namespace SilverOS.Welcome.App; - -public class Program -{ - // This is the main entry point of the application. - static void Main(string[] args) - { - // if you want to use a different Application Delegate class from "AppDelegate" - // you can specify it here. - UIApplication.Main(args, null, typeof(AppDelegate)); - } -} \ No newline at end of file diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/Tizen/Main.cs b/windows/welcome/src/SilverOS.Welcome.App/Platforms/Tizen/Main.cs deleted file mode 100644 index e273936..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/Tizen/Main.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using Microsoft.Maui; -using Microsoft.Maui.Hosting; - -namespace SilverOS.Welcome.App; - -class Program : MauiApplication -{ - protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); - - static void Main(string[] args) - { - var app = new Program(); - app.Run(args); - } -} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/Tizen/tizen-manifest.xml b/windows/welcome/src/SilverOS.Welcome.App/Platforms/Tizen/tizen-manifest.xml deleted file mode 100644 index 6680d35..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/Tizen/tizen-manifest.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - maui-appicon-placeholder - - - - - http://tizen.org/privilege/internet - - - - \ No newline at end of file diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/AppDelegate.cs b/windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/AppDelegate.cs deleted file mode 100644 index d1f3709..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/AppDelegate.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Foundation; - -namespace SilverOS.Welcome.App; - -[Register("AppDelegate")] -public class AppDelegate : MauiUIApplicationDelegate -{ - protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); -} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/Info.plist b/windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/Info.plist deleted file mode 100644 index ecb7f71..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/Info.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - LSRequiresIPhoneOS - - UIDeviceFamily - - 1 - 2 - - UIRequiredDeviceCapabilities - - arm64 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - XSAppIconAssets - Assets.xcassets/appicon.appiconset - - diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/Program.cs b/windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/Program.cs deleted file mode 100644 index 6d73368..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/Program.cs +++ /dev/null @@ -1,15 +0,0 @@ -using ObjCRuntime; -using UIKit; - -namespace SilverOS.Welcome.App; - -public class Program -{ - // This is the main entry point of the application. - static void Main(string[] args) - { - // if you want to use a different Application Delegate class from "AppDelegate" - // you can specify it here. - UIApplication.Main(args, null, typeof(AppDelegate)); - } -} diff --git a/windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/Resources/PrivacyInfo.xcprivacy b/windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/Resources/PrivacyInfo.xcprivacy deleted file mode 100644 index 24ab3b4..0000000 --- a/windows/welcome/src/SilverOS.Welcome.App/Platforms/iOS/Resources/PrivacyInfo.xcprivacy +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryFileTimestamp - NSPrivacyAccessedAPITypeReasons - - C617.1 - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategorySystemBootTime - NSPrivacyAccessedAPITypeReasons - - 35F9.1 - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryDiskSpace - NSPrivacyAccessedAPITypeReasons - - E174.1 - - - - - - diff --git a/windows/welcome/tests/SilverOS.Welcome.Tests/FlavourStepTests.cs b/windows/welcome/tests/SilverOS.Welcome.Tests/FlavourStepTests.cs new file mode 100644 index 0000000..972f05b --- /dev/null +++ b/windows/welcome/tests/SilverOS.Welcome.Tests/FlavourStepTests.cs @@ -0,0 +1,23 @@ +using Bunit; +using Microsoft.Extensions.DependencyInjection; +using SilverOS.Welcome.App.Components.Steps; +using SilverOS.Welcome.App.Components; +using SilverOS.Welcome.Core.Flavours; +using Xunit; + +public class FlavourStepTests : TestContext +{ + [Fact] + public void Renders_one_card_per_flavour_and_preselects_default() + { + var flavours = new[] + { + new FlavourManifest { Id="daily-driver", Label="Daily-Driver", IsDefault=true, Hardening=new(){Modules=new[]{"00"}} }, + new FlavourManifest { Id="privacy-max", Label="Privacy-Max", Hardening=new(){Modules=new[]{"00"}} }, + }; + Services.AddSingleton(new WizardState()); + var cut = RenderComponent(p => p.Add(s => s.Flavours, flavours)); + Assert.Equal(2, cut.FindAll(".flavour-card").Count); + Assert.Contains("selected", cut.Find(".flavour-card[data-id=daily-driver]").ClassList); + } +} diff --git a/windows/welcome/tests/SilverOS.Welcome.Tests/SilverOS.Welcome.Tests.csproj b/windows/welcome/tests/SilverOS.Welcome.Tests/SilverOS.Welcome.Tests.csproj index 7447e76..3e5ff02 100644 --- a/windows/welcome/tests/SilverOS.Welcome.Tests/SilverOS.Welcome.Tests.csproj +++ b/windows/welcome/tests/SilverOS.Welcome.Tests/SilverOS.Welcome.Tests.csproj @@ -1,13 +1,19 @@ - + - net9.0-windows + net9.0-windows10.0.19041.0 enable enable false + true + + Library + + true + @@ -20,7 +26,7 @@ - +