From 50de5f412f9b3d1d80fe4f5b32d3402239d3f40b Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sun, 23 Aug 2026 23:19:48 +0100 Subject: [PATCH 01/73] chore(release): bump version via gitversion for 1.0.8-rc3 --- src/PostIt.Tests/PostIt.Tests.csproj | 2 +- src/PostIt/PostIt.Android/PostIt.Android.csproj | 4 ++-- src/PostIt/PostIt.Browser/PostIt.Browser.csproj | 2 +- src/PostIt/PostIt.Desktop/PostIt.Desktop.csproj | 2 +- src/PostIt/PostIt/PostIt.csproj | 2 +- src/Yavsc.Abstract/Yavsc.Abstract.csproj | 2 +- src/Yavsc.Api.Client/Yavsc.Api.Client.csproj | 2 +- src/Yavsc.Api/Yavsc.Api.csproj | 2 +- src/Yavsc.Blogs.Tests/Yavsc.Blogs.Tests.csproj | 2 +- src/Yavsc.Blogs/Yavsc.Blogs.csproj | 2 +- src/Yavsc.Org.Tests/Yavsc.Org.Tests.csproj | 2 +- src/Yavsc.Org/Yavsc.Org.csproj | 2 +- src/Yavsc.Server/Yavsc.Server.csproj | 2 +- src/Yavsc.Tests.Shared/Yavsc.Tests.Shared.csproj | 2 +- src/cli/cli.csproj | 4 ++-- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/PostIt.Tests/PostIt.Tests.csproj b/src/PostIt.Tests/PostIt.Tests.csproj index b12c536e..b41c8137 100644 --- a/src/PostIt.Tests/PostIt.Tests.csproj +++ b/src/PostIt.Tests/PostIt.Tests.csproj @@ -8,7 +8,7 @@ true 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/PostIt/PostIt.Android/PostIt.Android.csproj b/src/PostIt/PostIt.Android/PostIt.Android.csproj index b34b88d4..40651399 100644 --- a/src/PostIt/PostIt.Android/PostIt.Android.csproj +++ b/src/PostIt/PostIt.Android/PostIt.Android.csproj @@ -14,7 +14,7 @@ android-arm;android-arm64;android-x86;android-x64 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 @@ -33,4 +33,4 @@ - + \ No newline at end of file diff --git a/src/PostIt/PostIt.Browser/PostIt.Browser.csproj b/src/PostIt/PostIt.Browser/PostIt.Browser.csproj index 8643fcc6..b3376ce7 100644 --- a/src/PostIt/PostIt.Browser/PostIt.Browser.csproj +++ b/src/PostIt/PostIt.Browser/PostIt.Browser.csproj @@ -6,7 +6,7 @@ enable 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/PostIt/PostIt.Desktop/PostIt.Desktop.csproj b/src/PostIt/PostIt.Desktop/PostIt.Desktop.csproj index 5043da6e..70795584 100644 --- a/src/PostIt/PostIt.Desktop/PostIt.Desktop.csproj +++ b/src/PostIt/PostIt.Desktop/PostIt.Desktop.csproj @@ -7,7 +7,7 @@ enable 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/PostIt/PostIt/PostIt.csproj b/src/PostIt/PostIt/PostIt.csproj index 163a6a77..0bef1f64 100644 --- a/src/PostIt/PostIt/PostIt.csproj +++ b/src/PostIt/PostIt/PostIt.csproj @@ -6,7 +6,7 @@ true 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/Yavsc.Abstract/Yavsc.Abstract.csproj b/src/Yavsc.Abstract/Yavsc.Abstract.csproj index 7a4f83ae..964ad179 100644 --- a/src/Yavsc.Abstract/Yavsc.Abstract.csproj +++ b/src/Yavsc.Abstract/Yavsc.Abstract.csproj @@ -11,7 +11,7 @@ latest 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/Yavsc.Api.Client/Yavsc.Api.Client.csproj b/src/Yavsc.Api.Client/Yavsc.Api.Client.csproj index ade7ca17..5be01943 100644 --- a/src/Yavsc.Api.Client/Yavsc.Api.Client.csproj +++ b/src/Yavsc.Api.Client/Yavsc.Api.Client.csproj @@ -17,7 +17,7 @@ true 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/Yavsc.Api/Yavsc.Api.csproj b/src/Yavsc.Api/Yavsc.Api.csproj index 5672ab7a..e714a0eb 100644 --- a/src/Yavsc.Api/Yavsc.Api.csproj +++ b/src/Yavsc.Api/Yavsc.Api.csproj @@ -7,7 +7,7 @@ true 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/Yavsc.Blogs.Tests/Yavsc.Blogs.Tests.csproj b/src/Yavsc.Blogs.Tests/Yavsc.Blogs.Tests.csproj index fc7883ce..8e4574aa 100644 --- a/src/Yavsc.Blogs.Tests/Yavsc.Blogs.Tests.csproj +++ b/src/Yavsc.Blogs.Tests/Yavsc.Blogs.Tests.csproj @@ -9,7 +9,7 @@ true 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/Yavsc.Blogs/Yavsc.Blogs.csproj b/src/Yavsc.Blogs/Yavsc.Blogs.csproj index 5c175cb5..aa54a758 100644 --- a/src/Yavsc.Blogs/Yavsc.Blogs.csproj +++ b/src/Yavsc.Blogs/Yavsc.Blogs.csproj @@ -8,7 +8,7 @@ true 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/Yavsc.Org.Tests/Yavsc.Org.Tests.csproj b/src/Yavsc.Org.Tests/Yavsc.Org.Tests.csproj index 88842cb4..672e8f5c 100644 --- a/src/Yavsc.Org.Tests/Yavsc.Org.Tests.csproj +++ b/src/Yavsc.Org.Tests/Yavsc.Org.Tests.csproj @@ -11,7 +11,7 @@ $(MSBuildProjectDirectory)\test.runsettings 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/Yavsc.Org/Yavsc.Org.csproj b/src/Yavsc.Org/Yavsc.Org.csproj index ccdb7f24..ef710ea9 100644 --- a/src/Yavsc.Org/Yavsc.Org.csproj +++ b/src/Yavsc.Org/Yavsc.Org.csproj @@ -9,7 +9,7 @@ https://github.com/pazof/yavsc 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/Yavsc.Server/Yavsc.Server.csproj b/src/Yavsc.Server/Yavsc.Server.csproj index 4eaf6a83..3eea8b3f 100644 --- a/src/Yavsc.Server/Yavsc.Server.csproj +++ b/src/Yavsc.Server/Yavsc.Server.csproj @@ -9,7 +9,7 @@ true 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/Yavsc.Tests.Shared/Yavsc.Tests.Shared.csproj b/src/Yavsc.Tests.Shared/Yavsc.Tests.Shared.csproj index 52effc72..a059b4a3 100644 --- a/src/Yavsc.Tests.Shared/Yavsc.Tests.Shared.csproj +++ b/src/Yavsc.Tests.Shared/Yavsc.Tests.Shared.csproj @@ -14,7 +14,7 @@ --> 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 diff --git a/src/cli/cli.csproj b/src/cli/cli.csproj index 010c4eaf..237ccdd8 100644 --- a/src/cli/cli.csproj +++ b/src/cli/cli.csproj @@ -7,7 +7,7 @@ true 1.1.0.0 1.1.0.0 - 1.1.0-beta.1+1.Branch.release-1.0.8-rc1.Sha.1167169aa89e1bf25290e9a152d27b357a500ab3 + 1.1.0-beta.1+49.Branch.release-1.0.8-rc3.Sha.5274d7bdf5d14406748a2063b5ae15191aac4359 1.1.0-beta.1 @@ -25,4 +25,4 @@ - + \ No newline at end of file From 01bc4782a01684528da41632651b2d385205d0ee Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sun, 23 Aug 2026 23:30:37 +0100 Subject: [PATCH 02/73] changes --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2a446a0..4147fc40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,21 @@ pour la production des paquets `.deb`. ## [1.0.8-rc1] - unstable +### Added + +* a code cleanup +* a failling a disabled test ala Xamarin.UITest : the Android app stil doesn't starts + +### Changed + +moslty nothing + +### Fixed + +nothing + +## [1.0.8-rc1] - unstable + ### Added - `BlogAclApiTests.PostCircleAuthorization_returns_201_when_payload_mirrors_PostIt_shape_against_existing_circle_named_test` : test de non-régression qui épingle la forme exacte du payload From 404bba56ab0d1399094b71e4316143d576422b99 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 24 Aug 2026 00:03:14 +0100 Subject: [PATCH 03/73] restores the legacy behavior --- src/PostIt/PostIt/App.axaml.cs | 6 ++--- .../Helpers/ServiceCollectionHelpers.cs | 2 +- src/PostIt/PostIt/ViewLocator.cs | 22 ++++++++----------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/PostIt/PostIt/App.axaml.cs b/src/PostIt/PostIt/App.axaml.cs index 10a0c8a5..b23a03f1 100644 --- a/src/PostIt/PostIt/App.axaml.cs +++ b/src/PostIt/PostIt/App.axaml.cs @@ -65,7 +65,10 @@ public partial class App : Application singleViewPlatform.MainView = CreateMainWindow(); ApplyDarkMode(settings); } + var mainVm = ServiceProvider!.GetRequiredService(); + base.OnFrameworkInitializationCompleted(); + this.PushPageAsync(mainVm).Wait(); } @@ -86,9 +89,6 @@ public partial class App : Application PushMainPageAsync().Wait(); }; - var homeVm = ServiceProvider!.GetRequiredService(); - - this.PushPageAsync(homeVm).Wait(); Window.SessionBanner.DataContext = sessionStatus; return Window; } diff --git a/src/PostIt/PostIt/Helpers/ServiceCollectionHelpers.cs b/src/PostIt/PostIt/Helpers/ServiceCollectionHelpers.cs index 9e0382de..fae24fa6 100644 --- a/src/PostIt/PostIt/Helpers/ServiceCollectionHelpers.cs +++ b/src/PostIt/PostIt/Helpers/ServiceCollectionHelpers.cs @@ -74,4 +74,4 @@ public static class ServiceCollectionHelpers return services.BuildServiceProvider(); } -} \ No newline at end of file +} diff --git a/src/PostIt/PostIt/ViewLocator.cs b/src/PostIt/PostIt/ViewLocator.cs index 03ab98a1..3543a9c9 100644 --- a/src/PostIt/PostIt/ViewLocator.cs +++ b/src/PostIt/PostIt/ViewLocator.cs @@ -16,12 +16,6 @@ namespace PostIt; Url = "https://docs.avaloniaui.net/docs/concepts/view-locator")] public class ViewLocator : IDataTemplate { - private readonly IServiceProvider _services; - - public ViewLocator(IServiceProvider services) - { - _services = services; - } public Control Build(object? data) { @@ -38,15 +32,17 @@ public class ViewLocator : IDataTemplate private Control BuildCore(object? data) { + var app = App.Current as App; + var services = app!.ServiceProvider!; return data switch { - MainViewModel => _services.GetRequiredService(), - Settings => _services.GetRequiredService(), - HomePageViewModel => _services.GetRequiredService(), - SignaturePageViewModel => _services.GetRequiredService(), - AddCircleMemberDialogViewModel => _services.GetRequiredService(), - CirclesPageViewModel => _services.GetRequiredService(), - PostAclDialogViewModel => _services.GetRequiredService(), + MainViewModel => services.GetRequiredService(), + Settings => services.GetRequiredService(), + HomePageViewModel => services.GetRequiredService(), + SignaturePageViewModel => services.GetRequiredService(), + AddCircleMemberDialogViewModel => services.GetRequiredService(), + CirclesPageViewModel => services.GetRequiredService(), + PostAclDialogViewModel => services.GetRequiredService(), null => new TextBlock { Text = "No view for " }, _ => new TextBlock { Text = $"No view for {data.GetType().Name}" } }; From 11aaf3678916438453f82796268ea7e9c7f28c5f Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 24 Aug 2026 00:17:43 +0100 Subject: [PATCH 04/73] updated --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4147fc40..73a4a88f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,20 +16,21 @@ Cette convention est partagée avec le dépôt [`postit-debian`](https://forgejo.pschneider.fr/notazof/postit-debian) pour la production des paquets `.deb`. -## [1.0.8-rc1] - unstable +## [1.0.8-rc3] - unstable ### Added * a code cleanup * a failling a disabled test ala Xamarin.UITest : the Android app stil doesn't starts +- Android app does not crash any more, but still no home page, only the splash screnn ### Changed -moslty nothing +mostly nothing ### Fixed -nothing +mostly nothing ## [1.0.8-rc1] - unstable From 246111dee146d4b92dfc2f4ed4891efcbeb33cb9 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 24 Aug 2026 00:18:07 +0100 Subject: [PATCH 05/73] Simpler is better --- src/PostIt/PostIt.Tests/AddCircleMemberDialogTests.cs | 2 -- src/PostIt/PostIt.Tests/MainPageButtonsTests.cs | 5 ----- src/PostIt/PostIt.Tests/PostAclDialogTests.cs | 2 -- 3 files changed, 9 deletions(-) diff --git a/src/PostIt/PostIt.Tests/AddCircleMemberDialogTests.cs b/src/PostIt/PostIt.Tests/AddCircleMemberDialogTests.cs index e2426457..91413ca0 100644 --- a/src/PostIt/PostIt.Tests/AddCircleMemberDialogTests.cs +++ b/src/PostIt/PostIt.Tests/AddCircleMemberDialogTests.cs @@ -100,8 +100,6 @@ public class AddCircleMemberDialogTests context.Window = new MainWindow(); context.App = (PostIt.App)Application.Current!; - context.App.DataTemplates.Clear(); - context.App.DataTemplates.Add(new ViewLocator(sp)); context.App.AttachMainWindow(context.Window); context.Window.Show(); diff --git a/src/PostIt/PostIt.Tests/MainPageButtonsTests.cs b/src/PostIt/PostIt.Tests/MainPageButtonsTests.cs index 3e7344a2..cd3684ef 100644 --- a/src/PostIt/PostIt.Tests/MainPageButtonsTests.cs +++ b/src/PostIt/PostIt.Tests/MainPageButtonsTests.cs @@ -114,11 +114,6 @@ public class MainPageButtonsTests var window = new MainWindow(); var page = new MainPage { DataContext = vm }; var app = (PostIt.App)Application.Current!; - if (vm.Services is not null) - { - app.DataTemplates.Clear(); - app.DataTemplates.Add(new ViewLocator(vm.Services)); - } app.AttachMainWindow(window); window.Show(); window.NavRoot.PushAsync(page).GetAwaiter().GetResult(); diff --git a/src/PostIt/PostIt.Tests/PostAclDialogTests.cs b/src/PostIt/PostIt.Tests/PostAclDialogTests.cs index 9bc28888..d13468f0 100644 --- a/src/PostIt/PostIt.Tests/PostAclDialogTests.cs +++ b/src/PostIt/PostIt.Tests/PostAclDialogTests.cs @@ -140,8 +140,6 @@ public class PostAclDialogTests var window = new MainWindow(); var app = (App)Application.Current!; - app.DataTemplates.Clear(); - app.DataTemplates.Add(new ViewLocator(sp)); app.AttachMainWindow(window); window.Show(); From 88e1499e4be5b69c45184258e6b35474be5f2914 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 24 Aug 2026 00:30:29 +0100 Subject: [PATCH 06/73] show the window --- src/PostIt/PostIt/App.axaml.cs | 5 +++-- src/PostIt/PostIt/Helpers/ViewModelBaseHelpers.cs | 9 +++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/PostIt/PostIt/App.axaml.cs b/src/PostIt/PostIt/App.axaml.cs index b23a03f1..1d0933a7 100644 --- a/src/PostIt/PostIt/App.axaml.cs +++ b/src/PostIt/PostIt/App.axaml.cs @@ -47,7 +47,7 @@ public partial class App : Application if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { - desktop.MainWindow = CreateMainWindow(); + desktop.MainWindow = Window = CreateMainWindow(); ApplyDarkMode(settings); } else if (ApplicationLifetime is IActivityApplicationLifetime singleViewFactoryApplicationLifetime) @@ -57,12 +57,13 @@ public partial class App : Application { Window = CreateMainWindow(); ApplyDarkMode(settings); + Window.Show(); return Window; }; } else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform) { - singleViewPlatform.MainView = CreateMainWindow(); + singleViewPlatform.MainView = Window = CreateMainWindow(); ApplyDarkMode(settings); } var mainVm = ServiceProvider!.GetRequiredService(); diff --git a/src/PostIt/PostIt/Helpers/ViewModelBaseHelpers.cs b/src/PostIt/PostIt/Helpers/ViewModelBaseHelpers.cs index 7fc81b3a..3cb00301 100644 --- a/src/PostIt/PostIt/Helpers/ViewModelBaseHelpers.cs +++ b/src/PostIt/PostIt/Helpers/ViewModelBaseHelpers.cs @@ -10,7 +10,8 @@ public static class ViewModelBaseHelpers { public static async Task PushPageAsync(this App app, ViewModelBase vm) { - if (app.Window is null) + var window = app.Window; + if (window is null) { throw new InvalidOperationException("MainWindow is not initialized yet."); } @@ -39,12 +40,12 @@ public static class ViewModelBaseHelpers page.DataContext = vm; // Avoid stacking the same singleton page twice (e.g. SettingsPage). - var stack = app.Window.NavRoot.NavigationStack; + var stack = window.NavRoot.NavigationStack; if (stack.Count > 0 && ReferenceEquals(stack[stack.Count - 1], page)) { return; } - await app.Window.NavRoot.PushAsync(page); + await window.NavRoot.PushAsync(page); } -} \ No newline at end of file +} From f62a020c82b913517cae5c772dc22e3c94259fe4 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 24 Aug 2026 01:23:15 +0100 Subject: [PATCH 07/73] don't wait from App Nav push ok on loggin succeded --- Makefile | 5 +++-- src/PostIt/PostIt/App.axaml.cs | 2 +- src/PostIt/PostIt/Views/MainPage.axaml | 11 +++++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index d6d69196..05aa5df2 100644 --- a/Makefile +++ b/Makefile @@ -163,7 +163,7 @@ POSTIT_RID ?= android-x64 EMU_HEADLESS ?= 0 LOGCAT_LINES ?= 600 LOGCAT_FOLLOW ?= 0 -LOGCAT_BOOT_WAIT ?= 20 +LOGCAT_BOOT_WAIT ?= 30 ANDROID_PACKAGE_NAME = fr.pschneider.PostIt POSTIT_ANDROID_CSPROJ := src/PostIt/PostIt.Android/PostIt.Android.csproj @@ -275,7 +275,8 @@ qemu-logcat-boot: @PID=$$(adb -s $(ADB_SERIAL) shell pidof $(ANDROID_PACKAGE_NAME) 2>/dev/null | tr -d '\r\n'); \ if [ -n "$$PID" ]; then \ echo " ✅ (PID $$PID at dump time)"; \ - adb -s $(ADB_SERIAL) logcat -d -v time --pid=$$PID; \ + sleep 10; \ + adb -s $(ADB_SERIAL) logcat -d -v time -t $(LOGCAT_LINES) --pid=$$PID; \ else \ echo " 👿 (PostIt process not running at dump time — dumping last $(LOGCAT_LINES) lines unfiltered)"; \ adb -s $(ADB_SERIAL) logcat -d -v time -t $(LOGCAT_LINES); \ diff --git a/src/PostIt/PostIt/App.axaml.cs b/src/PostIt/PostIt/App.axaml.cs index 1d0933a7..3b7370f9 100644 --- a/src/PostIt/PostIt/App.axaml.cs +++ b/src/PostIt/PostIt/App.axaml.cs @@ -87,7 +87,7 @@ public partial class App : Application sessionStatus.LoginSucceeded += () => { - PushMainPageAsync().Wait(); + PushMainPageAsync(); }; Window.SessionBanner.DataContext = sessionStatus; diff --git a/src/PostIt/PostIt/Views/MainPage.axaml b/src/PostIt/PostIt/Views/MainPage.axaml index 7f1f1196..d79253f6 100644 --- a/src/PostIt/PostIt/Views/MainPage.axaml +++ b/src/PostIt/PostIt/Views/MainPage.axaml @@ -97,7 +97,14 @@ - + + + From 7fabee1bd14657fa9ac4f1f0be85682f2bce456d Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 24 Aug 2026 01:43:47 +0100 Subject: [PATCH 08/73] restore the TextEditor --- src/PostIt/PostIt/Views/MainPage.axaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PostIt/PostIt/Views/MainPage.axaml b/src/PostIt/PostIt/Views/MainPage.axaml index d79253f6..fd75d403 100644 --- a/src/PostIt/PostIt/Views/MainPage.axaml +++ b/src/PostIt/PostIt/Views/MainPage.axaml @@ -97,14 +97,14 @@ - - - + --> + HorizontalScrollBarVisibility="Auto" /> From ce070453b20069beeb3f13b3a187dbe785665bb7 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 24 Aug 2026 16:25:45 +0100 Subject: [PATCH 09/73] It was too much for qemu --- Makefile | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 05aa5df2..9f1eca7f 100644 --- a/Makefile +++ b/Makefile @@ -124,12 +124,12 @@ release: # Cibles pour installer PostIt.Android en Debug sur l'AVD qemu. # # Usage typique : -# make qemu # lance l'AVD, attend le boot, build l'APK, l'installe -# make qemu-install # (re)build l'APK et l'installe (AVD doit tourner) -# make qemu-build # build l'APK seul (sans install) -# make qemu-run # démarre l'AVD en background -# make qemu-stop # arrête l'émulateur -# make qemu-wait-boot # attend que l'AVD ait fini de booter +# make qemu # lance l'AVD, attend le boot, build l'APK, l'installe +# make android-install # (re)build l'APK et l'installe (AVD doit tourner) +# make android-build # build l'APK seul (sans install) +# make qemu-run # démarre l'AVD en background +# make qemu-stop # arrête l'émulateur +# make qemu-wait-boot # attend que l'AVD ait fini de booter # # Variables surchargeables (make VAR=valeur) : # AVD_NAME default: postit_test_avd @@ -150,7 +150,7 @@ release: # LOGCAT_LINES default: 200 # (nombre de lignes dumpées par `make qemu-logcat`) # LOGCAT_FOLLOW default: 0 -# (1 = stream live via `make qemu-logcat`, +# (1 = stream live via `make logcat`, # sinon dump one-shot des N dernières lignes) # LOGCAT_BOOT_WAIT default: 30 # (secondes d'attente entre le clear du buffer, @@ -165,7 +165,7 @@ LOGCAT_LINES ?= 600 LOGCAT_FOLLOW ?= 0 LOGCAT_BOOT_WAIT ?= 30 -ANDROID_PACKAGE_NAME = fr.pschneider.PostIt +ANDROID_PACKAGE_NAME = fr.pschneider.postit POSTIT_ANDROID_CSPROJ := src/PostIt/PostIt.Android/PostIt.Android.csproj POSTIT_APK_DIR := src/PostIt/PostIt.Android/bin/$(CONFIG)/net10.0-android/$(POSTIT_RID) POSTIT_APK := $(POSTIT_APK_DIR)/$(ANDROID_PACKAGE_NAME)-Signed.apk @@ -197,7 +197,7 @@ qemu-wait-boot: echo " Logs: /tmp/yavsc-emu/$(AVD_NAME).log" >&2; \ exit 1 -qemu-build: +android-build: # EmbedAssembliesIntoApk=true: without this, the Debug APK ships # without the managed assemblies in it (they are pushed at runtime # via `adb push`, "Fast Deployment"). On the qemu emulator, the @@ -223,7 +223,7 @@ qemu-build: fi -qemu-install: qemu-build +android-install: android-build @echo " Installing $(POSTIT_APK) on $(ADB_SERIAL)..." adb -s $(ADB_SERIAL) install -r "$(POSTIT_APK)" -r @@ -240,7 +240,7 @@ qemu-uninstall: # If the app is not running, pidof returns empty and logcat exits # silently with no output; that is the expected behaviour for # "no logs yet". -qemu-logcat: +logcat: @PID=$$(adb -s $(ADB_SERIAL) shell pidof $(ANDROID_PACKAGE_NAME) 2>/dev/null | tr -d '\r\n'); \ if [ -z "$$PID" ]; then \ echo " $(ANDROID_PACKAGE_NAME) is not running on $(ADB_SERIAL)."; \ @@ -262,12 +262,16 @@ qemu-logcat: # Override LOGCAT_BOOT_WAIT to extend the post-launch wait # (default 15s; raise to 30+ if the device is slow to boot Avalonia). LOGCAT_BOOT_WAIT ?= 15 -qemu-logcat-boot: + + +android-start: @echo " Clearing logcat buffer..." adb -s $(ADB_SERIAL) logcat -c @echo " Launching $(ANDROID_PACKAGE_NAME)..." adb -s $(ADB_SERIAL) shell am start \ -n $(ANDROID_PACKAGE_NAME)/PostIt.Android.PostItMainActivity + +qemu-logcat-boot: android-start @echo " Waiting $(LOGCAT_BOOT_WAIT)s for the app to start rendering..." @sleep $(LOGCAT_BOOT_WAIT) @@ -283,7 +287,7 @@ qemu-logcat-boot: exit 1; \ fi -qemu: qemu-run qemu-wait-boot qemu-install +qemu: qemu-run qemu-wait-boot android-install @echo " ✓ PostIt.Android installed on $(ADB_SERIAL)" -.PHONY: test release qemu qemu-run qemu-stop qemu-wait-boot qemu-build qemu-install qemu-logcat qemu-logcat-boot +.PHONY: test release qemu qemu-run qemu-stop qemu-wait-boot android-build android-install logcat qemu-logcat-boot From a079c56c08116143b508a8a5f792065327aa052a Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 24 Aug 2026 16:26:23 +0100 Subject: [PATCH 10/73] code format --- .vscode/launch.json | 84 ++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 42be176a..7ea523c9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,10 +1,10 @@ { - // Utilisez IntelliSense pour en savoir plus sur les attributs possibles. - // Pointez pour afficher la description des attributs existants. - // Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { + // Utilisez IntelliSense pour en savoir plus sur les attributs possibles. + // Pointez pour afficher la description des attributs existants. + // Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { "name": "Debug - Android", "type": "mono", "preLaunchTask": "run-debug-android", @@ -19,41 +19,39 @@ "address": "localhost", "port": 10000 }, - { - "name": "API", - "type": "dotnet", - "request": "launch", - "projectPath": "${workspaceFolder}/src/Api/Api.csproj" - }, - { - "name": "Yavsc.Org", - "type": "dotnet", - "request": "launch", - "projectPath": "${workspaceFolder}/src/Yavsc.Org/Yavsc.Org.csproj", - }, - { - "name": "Yavsc.Blogs", - "type": "dotnet", - "request": "launch", - "projectPath": "${workspaceFolder}/src/Yavsc.Blogs/Yavsc.Blogs.csproj" - }, - { - "name": "PostIt", - "type": "dotnet", - "request": "launch", - "projectPath": "${workspaceFolder}/src/PostIt/PostIt.Desktop/PostIt.Desktop.csproj", - - }, - { - "name": "Test PostIt.Android launch (Xamarin.UITest)", - "type": "coreclr", - "request": "launch", - "program": "${workspaceFolder}/src/PostIt/PostIt.Tests/bin/Debug/net10.0/PostIt.Tests.dll", - "args": [ - ], - "cwd": "${workspaceFolder}/src/PostIt/PostIt.Tests", - "console": "integratedTerminal", - "stopAtEntry": false - } - ] + { + "name": "API", + "type": "dotnet", + "request": "launch", + "projectPath": "${workspaceFolder}/src/Api/Api.csproj" + }, + { + "name": "Yavsc.Org", + "type": "dotnet", + "request": "launch", + "projectPath": "${workspaceFolder}/src/Yavsc.Org/Yavsc.Org.csproj", + }, + { + "name": "Yavsc.Blogs", + "type": "dotnet", + "request": "launch", + "projectPath": "${workspaceFolder}/src/Yavsc.Blogs/Yavsc.Blogs.csproj" + }, + { + "name": "PostIt", + "type": "dotnet", + "request": "launch", + "projectPath": "${workspaceFolder}/src/PostIt/PostIt.Desktop/PostIt.Desktop.csproj", + }, + { + "name": "Test PostIt.Android launch (Xamarin.UITest)", + "type": "coreclr", + "request": "launch", + "program": "${workspaceFolder}/src/PostIt/PostIt.Tests/bin/Debug/net10.0/PostIt.Tests.dll", + "args": [], + "cwd": "${workspaceFolder}/src/PostIt/PostIt.Tests", + "console": "integratedTerminal", + "stopAtEntry": false + } + ] } From a450be6f249577d5e0a19808e8a4c814e033a61e Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 24 Aug 2026 16:26:42 +0100 Subject: [PATCH 11/73] simpler is better --- .vscode/tasks.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index c900fa6a..a80c4741 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -10,13 +10,11 @@ "env": { "DOTNET_HOST_PATH": "/usr/share/dotnet", "ANDROID_HOME": "/opt/android-sdk", - "JAVA_HOME": "/usr/lib/jvm/java-1.21.0-openjdk-amd64" + "JAVA_HOME": "/usr/lib/jvm/java-1.25.0-openjdk-amd64" } }, "args": [ - "build" - "-t:run", - "-p:TargetFramework=net10.0-android", + "run", "-p:Configuration=Debug", "-p:AndroidAttachDebugger=true", "-p:AndroidSdbHostPort=10000", From beeac586284dfca3a10df7a283d79a047ff39b43 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 25 Aug 2026 14:16:49 +0100 Subject: [PATCH 12/73] test are still ok! --- .vscode/launch.json | 2 +- .vscode/tasks.json | 70 +++++-------------- Directory.Build.props | 2 +- src/PostIt/Directory.Packages.props | 36 +++++----- src/PostIt/Makefile | 7 ++ src/PostIt/PostIt.Android/MainActivity.cs | 23 ++++-- .../PostIt.Android/PostIt.Android.csproj | 12 ++-- .../Resources/values/font_certs.xml | 13 ++++ .../AddCircleMemberDialogTests.cs | 5 +- .../PostIt.Tests/AndroidAppLaunchTests.cs | 2 +- .../PostIt.Tests/MainPageButtonsTests.cs | 11 ++- src/PostIt/PostIt.Tests/PostAclDialogTests.cs | 5 +- .../PostIt.Tests/SessionStatusBannerTests.cs | 17 ++--- src/PostIt/PostIt.Tests/TestAppContext.cs | 2 +- src/PostIt/PostIt.Tests/UnitTest1.cs | 3 +- src/PostIt/PostIt/App.axaml | 1 - src/PostIt/PostIt/App.axaml.cs | 62 ++++++++-------- .../Helpers/ServiceCollectionHelpers.cs | 7 +- .../PostIt/Helpers/ViewModelBaseHelpers.cs | 2 +- src/PostIt/PostIt/PostIt.csproj | 1 - .../PostIt/Services/ContactService.Desktop.cs | 36 ---------- src/PostIt/PostIt/Views/MainPage.axaml | 14 +--- src/PostIt/PostIt/Views/MainView.axaml | 22 ++++++ src/PostIt/PostIt/Views/MainView.axaml.cs | 11 +++ src/PostIt/PostIt/Views/MainWindow.axaml | 9 +-- src/PostIt/PostIt/Views/MainWindow.axaml.cs | 2 +- src/PostIt/PostIt/Views/TextEditorBinding.cs | 51 -------------- 27 files changed, 170 insertions(+), 258 deletions(-) create mode 100644 src/PostIt/Makefile create mode 100644 src/PostIt/PostIt.Android/Resources/values/font_certs.xml delete mode 100644 src/PostIt/PostIt/Services/ContactService.Desktop.cs create mode 100644 src/PostIt/PostIt/Views/MainView.axaml create mode 100644 src/PostIt/PostIt/Views/MainView.axaml.cs delete mode 100644 src/PostIt/PostIt/Views/TextEditorBinding.cs diff --git a/.vscode/launch.json b/.vscode/launch.json index 7ea523c9..36dc17a2 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "name": "Debug - Android", + "name": "Android", "type": "mono", "preLaunchTask": "run-debug-android", "request": "attach", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index a80c4741..9fe9caaf 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -15,12 +15,27 @@ }, "args": [ "run", + "-p:TargetFramework=net10.0-android", "-p:Configuration=Debug", "-p:AndroidAttachDebugger=true", "-p:AndroidSdbHostPort=10000", "-p:AndroidSdbTargetPort=10000" ], - "problemMatcher": "$msCompile" + "problemMatcher": [ + { + "owner": "dotnet", + "fileLocation": ["relative", "${workspaceFolder}"], + "source": "dotnet", + "pattern": { + "regexp": "^(.*):(\\d+):(\\d+):\\s+(error):\\s+(.*)$", + "file": 1, + "line": 2, + "column": 3, + "severity": 4, + "message": 5 + } + } + ] }, { "label": "build", @@ -60,59 +75,6 @@ "kind": "build" }, "isBackground": true - }, - { - "label": "test blogs", - "type": "process", - "problemMatcher": ["$msCompile"], - "command": "dotnet", - "args": ["test"], - "runOptions": { - "instanceLimit": 1 - }, - "options": { - "cwd": "src/Yavsc.Blogs", - "env": { - "DOTNET_CLI_UI_LANGUAGE": "en-US", - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "group": { - "kind": "test" - }, - "isBackground": true, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "shared", - "showReuseMessage": true, - "clear": false - } - }, - { - "label": "publish", - "command": "dotnet", - "type": "process", - "args": [ - "publish", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary;ForceNoAlign" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "watch", - "command": "dotnet", - "type": "process", - "args": ["watch", "--project", - "src/Yavsc.Org/Yavsc.Org.csproj" - ], - "problemMatcher": "$msCompile", - "runOptions": { - - } - } ] } diff --git a/Directory.Build.props b/Directory.Build.props index aec8c990..0ce825bd 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -11,6 +11,6 @@ from without conflicting names. --> true - NU1701, NU1901, NU1902 + NU1701, NU1901, NU1902, NU1507 diff --git a/src/PostIt/Directory.Packages.props b/src/PostIt/Directory.Packages.props index 69e8a896..0d5fa50c 100644 --- a/src/PostIt/Directory.Packages.props +++ b/src/PostIt/Directory.Packages.props @@ -5,33 +5,35 @@ true + 12.1.1 - - - - - - - - - + + + + + + + + + - + - - - - - - - + + + + + + + + diff --git a/src/PostIt/Makefile b/src/PostIt/Makefile new file mode 100644 index 00000000..72158bfa --- /dev/null +++ b/src/PostIt/Makefile @@ -0,0 +1,7 @@ + +clean: clean-PostIt clean-PostIt.Android clean-PostIt.Desktop + +clean-%: + rm -rf $*/obj $*/bin + +.PHONY: clean diff --git a/src/PostIt/PostIt.Android/MainActivity.cs b/src/PostIt/PostIt.Android/MainActivity.cs index 62c29e10..4f788550 100644 --- a/src/PostIt/PostIt.Android/MainActivity.cs +++ b/src/PostIt/PostIt.Android/MainActivity.cs @@ -1,8 +1,13 @@ -using Android.App; +using Android; +using Android.App; using Android.Content; using Android.Content.PM; +using AndroidX.Core.Provider; +using AndroidX.Emoji2.Text; using Avalonia; using Avalonia.Android; +using AndroidX.Core.Provider; +using AndroidX.Emoji2.Text; namespace PostIt.Android; @@ -15,18 +20,22 @@ namespace PostIt.Android; ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)] public class MainActivity : AvaloniaMainActivity { - /// - /// Strongly-typed handle to the current MainActivity instance, set in - /// and consumed by platform services such as - /// which need to launch - /// Chrome Custom Tabs. + /// + /// The current MainActivity instance. /// public static MainActivity? Current { get; private set; } protected override void OnCreate(global::Android.OS.Bundle? savedInstanceState) { - base.OnCreate(savedInstanceState); + FontRequest fontRequest = new FontRequest( + "com.google.android.gms.fonts", + "com.google.android.gms", + "Noto Color Emoji Compat", + Yavsc.Resource.Array.com_google_android_gms_fonts_certs); //com_google_android_gms_fonts_certs + EmojiCompat.Config config = new FontRequestEmojiCompatConfig(this, fontRequest); + EmojiCompat.Init(config); PlatformBootstrap.EnsureInitialized(); + base.OnCreate(savedInstanceState); Current = this; } /// diff --git a/src/PostIt/PostIt.Android/PostIt.Android.csproj b/src/PostIt/PostIt.Android/PostIt.Android.csproj index a4af1eb2..62b494f8 100644 --- a/src/PostIt/PostIt.Android/PostIt.Android.csproj +++ b/src/PostIt/PostIt.Android/PostIt.Android.csproj @@ -4,13 +4,11 @@ net10.0-android 23 enable - fr.pschneider.PostIt + fr.pschneider.postit 1 1.0 apk - false - SdkOnly - partial + false @@ -23,11 +21,11 @@ - - - + + + diff --git a/src/PostIt/PostIt.Android/Resources/values/font_certs.xml b/src/PostIt/PostIt.Android/Resources/values/font_certs.xml new file mode 100644 index 00000000..f4adce1b --- /dev/null +++ b/src/PostIt/PostIt.Android/Resources/values/font_certs.xml @@ -0,0 +1,13 @@ + + + + @array/com_google_android_gms_fonts_certs_dev + @array/com_google_android_gms_fonts_certs_prod + + + MIIEqDCCA5CgAwIBAgIJAN5gc16AJfAsMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRAwDgYDVQQDEwdBbmRyb2lkMSEwHwYJKoZIhvcNAQkBFhJhbmRyb2lkQGFuZHJvaWQuY29tMCAXDTA4MDQxNTIyNDA0M1YYDzQyMDgxMzA0MjI0MDQzWjCBlDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDURvdW50YWluIFZpZXcxEDAOBgNVBAoTB0dvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEhMB8GCSqGSIb3DQEJARYSYW5kcm9pZEBhbmRyb2lkLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALBi1vF0K1vOEHG7AxneTjOHUka46MIidBqvFcO164A49iU2DkYPhUaM4H8JCdzh6N1GzM6h9o6E2V6z8+gEtdI6nqqs0EGA0G0H701bFjLp9+K/1DkMIFeD4P8J7X1/M8t4+X09X/7bQyV3w0v7q+Qh38sY8W/7K29B3f2O2sLw+uX9U8a8Tf4Xv8A== + + + MIIEQzCCAyugAwIBAgIJAMLgh0ZgXpYOMA0GCSqGSIb3DQEBBQUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4MjEyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKvSkUIXm+t9M8rXj2V + + diff --git a/src/PostIt/PostIt.Tests/AddCircleMemberDialogTests.cs b/src/PostIt/PostIt.Tests/AddCircleMemberDialogTests.cs index 91413ca0..8bec1dc6 100644 --- a/src/PostIt/PostIt.Tests/AddCircleMemberDialogTests.cs +++ b/src/PostIt/PostIt.Tests/AddCircleMemberDialogTests.cs @@ -73,7 +73,7 @@ public class AddCircleMemberDialogTests return context; } /// - /// Mount a real , build a minimal + /// Mount a real , build a minimal /// DI graph, push then the /// on top of it. /// Returns the stack size so the test can pin the delta. @@ -98,10 +98,9 @@ public class AddCircleMemberDialogTests services.AddTransient(); var sp = services.BuildServiceProvider(); - context.Window = new MainWindow(); + context.Window = new MainView(); context.App = (PostIt.App)Application.Current!; context.App.AttachMainWindow(context.Window); - context.Window.Show(); context.page = sp.GetRequiredService(); context.Window.NavRoot.PushAsync(context.page).GetAwaiter().GetResult(); diff --git a/src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs b/src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs index ac4756eb..23b423e1 100644 --- a/src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs +++ b/src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs @@ -23,7 +23,7 @@ public class AndroidAppLaunchTests _output = output; } - // FIXME [Fact] + [Fact] public void PostIt_starts_and_draws_a_first_frame_on_the_emulator() { if (!IsPackageInstalledOnAnyDevice()) diff --git a/src/PostIt/PostIt.Tests/MainPageButtonsTests.cs b/src/PostIt/PostIt.Tests/MainPageButtonsTests.cs index cd3684ef..d1d00532 100644 --- a/src/PostIt/PostIt.Tests/MainPageButtonsTests.cs +++ b/src/PostIt/PostIt.Tests/MainPageButtonsTests.cs @@ -99,7 +99,7 @@ public class MainPageButtonsTests } /// - /// Mount a real (as + /// Mount a real (as /// SessionStatusBannerTests does), push a /// with the given VM onto /// NavRoot. PushAsync is awaited (via @@ -109,13 +109,12 @@ public class MainPageButtonsTests /// realised and KeyPressQwerty has a real /// to dispatch against. /// - private static (MainWindow window, MainPage page) MountMainPage(MainViewModel vm) + private static (MainView window, MainPage page) MountMainPage(MainViewModel vm) { - var window = new MainWindow(); + var window = new MainView(); var page = new MainPage { DataContext = vm }; var app = (PostIt.App)Application.Current!; app.AttachMainWindow(window); - window.Show(); window.NavRoot.PushAsync(page).GetAwaiter().GetResult(); return (window, page); } @@ -125,7 +124,7 @@ public class MainPageButtonsTests /// supported headless pattern (cf. CalculatorTests in the /// Avalonia.Samples repo). Returns the nav-stack count /// before the click so the caller can assert on the delta. - /// KeyPressQwerty is dispatched on the + /// KeyPressQwerty is dispatched on the /// itself — it is the that owns the /// headless implementation, and routing the key through any /// descendant TopLevel (e.g. one obtained via @@ -134,7 +133,7 @@ public class MainPageButtonsTests /// because the descendant does not carry the /// PlatformHandle the harness expects. /// - private static int ClickAndCapture(MainWindow window, Button button) + private static int ClickAndCapture(MainView window, Button button) { var stackBefore = window.NavRoot.NavigationStack.Count; button.Command?.Execute(button.CommandParameter); diff --git a/src/PostIt/PostIt.Tests/PostAclDialogTests.cs b/src/PostIt/PostIt.Tests/PostAclDialogTests.cs index d13468f0..ccb33ec7 100644 --- a/src/PostIt/PostIt.Tests/PostAclDialogTests.cs +++ b/src/PostIt/PostIt.Tests/PostAclDialogTests.cs @@ -117,7 +117,7 @@ public class PostAclDialogTests /// rebinding the global DI mid-test would trample the /// Settings singleton the rest of the harness depends on. /// - private static (MainWindow window, BlogAclApiClient aclClient, CircleApiClient circleClient, CountingHttpHandler handler) Mount() + private static (MainView window, BlogAclApiClient aclClient, CircleApiClient circleClient, CountingHttpHandler handler) Mount() { var handler = new CountingHttpHandler(); var settings = new Settings(); @@ -138,10 +138,9 @@ public class PostAclDialogTests // CountingHttpHandler. GC.KeepAlive(sp); - var window = new MainWindow(); + var window = new MainView(); var app = (App)Application.Current!; app.AttachMainWindow(window); - window.Show(); return (window, aclClient, circleClient, handler); } diff --git a/src/PostIt/PostIt.Tests/SessionStatusBannerTests.cs b/src/PostIt/PostIt.Tests/SessionStatusBannerTests.cs index e1a5dd19..0a28ee87 100644 --- a/src/PostIt/PostIt.Tests/SessionStatusBannerTests.cs +++ b/src/PostIt/PostIt.Tests/SessionStatusBannerTests.cs @@ -9,7 +9,7 @@ namespace PostIt.Tests; /// /// UI tests for . Mounted inside -/// a real via the headless Avalonia +/// a real via the headless Avalonia /// platform declared in TestApp.cs. /// /// The pattern is the one that UnitTest1.MainPage_Should_Load @@ -34,9 +34,8 @@ public class SessionStatusBannerTests [AvaloniaFact] public void Banner_renders_three_buttons_in_the_visual_tree() { - var window = new MainWindow(); + var window = new MainView(); window.SessionBanner.DataContext = new SessionStatusViewModel(); - window.Show(); var buttons = window.SessionBanner.GetVisualDescendants() .OfType public IServiceProvider? ServiceProvider { get; private set; } - public MainWindow? Window { get; private set; } + public MainView? View { get; private set; } public override void Initialize() { @@ -44,10 +44,28 @@ public partial class App : Application this.ServiceProvider = new ServiceCollection().BuildServices(); var settings = ServiceProvider.GetRequiredService(); + var sessionStatus = ServiceProvider!.GetRequiredService(); + sessionStatus.LogoutCompleted += () => + { + View.NavRoot.PopToRootAsync(); + }; + sessionStatus.LoginSucceeded += () => + { + PushMainPageAsync(); + }; if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { - desktop.MainWindow = Window = CreateMainWindow(); + var window = ServiceProvider.GetRequiredService(); + desktop.MainWindow = window; + var api = ServiceProvider!.GetRequiredService(); + desktop.MainWindow.Opened += async (_, _) => await BootAsync(this.ServiceProvider!, api); + + View = window.MainView; + + View.SessionBanner.DataContext = sessionStatus; + // FIXME Window.Opened += async (_, _) => await BootAsync(this.ServiceProvider!, api); + ApplyDarkMode(settings); } else if (ApplicationLifetime is IActivityApplicationLifetime singleViewFactoryApplicationLifetime) @@ -55,54 +73,34 @@ public partial class App : Application singleViewFactoryApplicationLifetime.MainViewFactory = () => { - Window = CreateMainWindow(); + View = ServiceProvider.GetRequiredService(); ApplyDarkMode(settings); - Window.Show(); - return Window; + View.SessionBanner.DataContext = sessionStatus; + return View; }; } else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform) { - singleViewPlatform.MainView = Window = CreateMainWindow(); + singleViewPlatform.MainView = View = ServiceProvider.GetRequiredService(); + View.SessionBanner.DataContext = sessionStatus; ApplyDarkMode(settings); } var mainVm = ServiceProvider!.GetRequiredService(); base.OnFrameworkInitializationCompleted(); - this.PushPageAsync(mainVm).Wait(); + this.PushPageAsync(mainVm); } - - private MainWindow CreateMainWindow() - { - Window = new MainWindow(); - var api = ServiceProvider!.GetRequiredService(); - Window.Opened += async (_, _) => await BootAsync(this.ServiceProvider!, api); - var sessionStatus = ServiceProvider!.GetRequiredService(); - sessionStatus.LogoutCompleted += () => - { - Window.NavRoot.PopToRootAsync(); - }; - - sessionStatus.LoginSucceeded += () => - { - PushMainPageAsync(); - }; - - Window.SessionBanner.DataContext = sessionStatus; - return Window; - } - /// - /// Test-only hook: bind a concrete so + /// Test-only hook: bind a concrete so /// command-driven navigation paths () can /// push onto a real in headless /// fixtures that do not run the full desktop lifetime bootstrap. /// - internal void AttachMainWindow(MainWindow mainWindow) + internal void AttachMainWindow(MainView mainWindow) { - Window = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); + View = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); } private static void ApplyDarkMode(Settings settings) @@ -180,6 +178,6 @@ public partial class App : Application internal async Task GoBackAsync() { - await Window!.NavRoot.PopAsync(); + await View!.NavRoot.PopAsync(); } } diff --git a/src/PostIt/PostIt/Helpers/ServiceCollectionHelpers.cs b/src/PostIt/PostIt/Helpers/ServiceCollectionHelpers.cs index fae24fa6..c4e774cc 100644 --- a/src/PostIt/PostIt/Helpers/ServiceCollectionHelpers.cs +++ b/src/PostIt/PostIt/Helpers/ServiceCollectionHelpers.cs @@ -23,11 +23,13 @@ public static class ServiceCollectionHelpers var circleClient = new CircleApiClient(api, settings.BlogsApiUrl); var blogAclClient = new BlogAclApiClient(api, settings.BlogsApiUrl); var userSearchClient = new UserSearchClient(api, settings.BlogsApiUrl); - var contactService = new ContactService(); var userDirectory = new UserDirectory(userSearchClient); // Vues - services.AddTransient(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + // SettingsPage is a singleton: there must be one and only one // instance of the settings UI for the lifetime of the app. // This guarantees that (a) the bindings always reflect the @@ -58,7 +60,6 @@ public static class ServiceCollectionHelpers services.AddSingleton(circleClient); services.AddSingleton(blogAclClient); services.AddSingleton(userSearchClient); - services.AddSingleton(contactService); services.AddSingleton(userDirectory); services.AddTransient(); services.AddTransient(); diff --git a/src/PostIt/PostIt/Helpers/ViewModelBaseHelpers.cs b/src/PostIt/PostIt/Helpers/ViewModelBaseHelpers.cs index 3cb00301..e4250cbb 100644 --- a/src/PostIt/PostIt/Helpers/ViewModelBaseHelpers.cs +++ b/src/PostIt/PostIt/Helpers/ViewModelBaseHelpers.cs @@ -10,7 +10,7 @@ public static class ViewModelBaseHelpers { public static async Task PushPageAsync(this App app, ViewModelBase vm) { - var window = app.Window; + var window = app.View; if (window is null) { throw new InvalidOperationException("MainWindow is not initialized yet."); diff --git a/src/PostIt/PostIt/PostIt.csproj b/src/PostIt/PostIt/PostIt.csproj index 70bd72ca..bde8fd41 100644 --- a/src/PostIt/PostIt/PostIt.csproj +++ b/src/PostIt/PostIt/PostIt.csproj @@ -28,7 +28,6 @@ All - diff --git a/src/PostIt/PostIt/Services/ContactService.Desktop.cs b/src/PostIt/PostIt/Services/ContactService.Desktop.cs deleted file mode 100644 index fa7d37f6..00000000 --- a/src/PostIt/PostIt/Services/ContactService.Desktop.cs +++ /dev/null @@ -1,36 +0,0 @@ -#if !ANDROID && !IOS -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace PostIt.Services; - -/// -/// Desktop stub for . -/// -/// The desktop has no equivalent of the mobile address -/// book (no Contacts.Default, no CardDAV out of the -/// box). Rather than synthesise a list from a different -/// source, this provider returns an empty list and lets the -/// UI render an honest "no local contacts on this platform" -/// message. -/// -/// If desktop users want to invite people who aren't -/// Yavsc members, that flow goes through a separate path -/// (manual email entry + invitation endpoint) — not through -/// . Finding existing Yavsc -/// members is 's job, not this -/// one's. -/// -/// Future CardDAV / Google Contacts / Exchange -/// providers can plug in here as additional -/// implementations selected -/// from DI by configuration. -/// -public sealed class ContactService : IContactService -{ - public Task> GetDeviceContactsAsync(CancellationToken ct = default) - => Task.FromResult>(Array.Empty()); -} -#endif diff --git a/src/PostIt/PostIt/Views/MainPage.axaml b/src/PostIt/PostIt/Views/MainPage.axaml index fd75d403..e44f9f99 100644 --- a/src/PostIt/PostIt/Views/MainPage.axaml +++ b/src/PostIt/PostIt/Views/MainPage.axaml @@ -97,23 +97,15 @@ - - + diff --git a/src/PostIt/PostIt/Views/MainView.axaml b/src/PostIt/PostIt/Views/MainView.axaml new file mode 100644 index 00000000..643c0f20 --- /dev/null +++ b/src/PostIt/PostIt/Views/MainView.axaml @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/src/PostIt/PostIt/Views/MainView.axaml.cs b/src/PostIt/PostIt/Views/MainView.axaml.cs new file mode 100644 index 00000000..74f46686 --- /dev/null +++ b/src/PostIt/PostIt/Views/MainView.axaml.cs @@ -0,0 +1,11 @@ +using Avalonia.Controls; + +namespace PostIt.Views; + +public partial class MainView : UserControl +{ + public MainView() + { + InitializeComponent(); + } +} diff --git a/src/PostIt/PostIt/Views/MainWindow.axaml b/src/PostIt/PostIt/Views/MainWindow.axaml index 060e0944..e606cf2b 100644 --- a/src/PostIt/PostIt/Views/MainWindow.axaml +++ b/src/PostIt/PostIt/Views/MainWindow.axaml @@ -7,11 +7,6 @@ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="PostIt.Views.MainWindow" Icon="/Assets/avalonia-logo.ico" - Title="PostIt" > - - - - - + Title="PostIt"> + diff --git a/src/PostIt/PostIt/Views/MainWindow.axaml.cs b/src/PostIt/PostIt/Views/MainWindow.axaml.cs index 9cb85f55..0dd9280a 100644 --- a/src/PostIt/PostIt/Views/MainWindow.axaml.cs +++ b/src/PostIt/PostIt/Views/MainWindow.axaml.cs @@ -8,4 +8,4 @@ public partial class MainWindow : Window { InitializeComponent(); } -} \ No newline at end of file +} diff --git a/src/PostIt/PostIt/Views/TextEditorBinding.cs b/src/PostIt/PostIt/Views/TextEditorBinding.cs deleted file mode 100644 index 56fda68c..00000000 --- a/src/PostIt/PostIt/Views/TextEditorBinding.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Avalonia; -using Avalonia.Data; -using AvaloniaEdit; - -namespace PostIt.Views; - -public sealed class TextEditorBinding -{ - public static readonly AttachedProperty TextProperty = - AvaloniaProperty.RegisterAttached( - "Text", - defaultBindingMode: BindingMode.TwoWay); - - private static readonly AttachedProperty IsTextChangeSubscribedProperty = - AvaloniaProperty.RegisterAttached("IsTextChangeSubscribed"); - - static TextEditorBinding() - { - TextProperty.Changed.AddClassHandler((editor, args) => - { - EnsureTextChangeSubscribed(editor); - - var text = args.GetNewValue() ?? string.Empty; - if (editor.Text != text) - { - editor.Text = text; - } - }); - } - - public static string? GetText(TextEditor editor) => editor.GetValue(TextProperty); - - public static void SetText(TextEditor editor, string? value) => editor.SetValue(TextProperty, value); - - private static void EnsureTextChangeSubscribed(TextEditor editor) - { - if (editor.GetValue(IsTextChangeSubscribedProperty)) - { - return; - } - - editor.SetValue(IsTextChangeSubscribedProperty, true); - editor.TextChanged += (_, _) => - { - if (editor.Text != GetText(editor)) - { - SetText(editor, editor.Text); - } - }; - } -} From dd5904f0a7324f8534ccb9d6518095e467ad984d Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 25 Aug 2026 14:53:25 +0100 Subject: [PATCH 13/73] refacto Makefiles and MainView setup --- Makefile | 171 +------------------------------- src/PostIt/Makefile | 173 ++++++++++++++++++++++++++++++++- src/PostIt/PostIt/App.axaml.cs | 39 +++++--- 3 files changed, 197 insertions(+), 186 deletions(-) diff --git a/Makefile b/Makefile index 9f1eca7f..fa9d4ecf 100644 --- a/Makefile +++ b/Makefile @@ -121,173 +121,4 @@ release: git push -u origin "$$BRANCH"; \ echo "==> Terminé. Branche $$BRANCH live sur origin." -# Cibles pour installer PostIt.Android en Debug sur l'AVD qemu. -# -# Usage typique : -# make qemu # lance l'AVD, attend le boot, build l'APK, l'installe -# make android-install # (re)build l'APK et l'installe (AVD doit tourner) -# make android-build # build l'APK seul (sans install) -# make qemu-run # démarre l'AVD en background -# make qemu-stop # arrête l'émulateur -# make qemu-wait-boot # attend que l'AVD ait fini de booter -# -# Variables surchargeables (make VAR=valeur) : -# AVD_NAME default: postit_test_avd -# (l'AVD doit être listé par `avdmanager list avd`) -# ADB_SERIAL default: emulator-5554 -# (port standard du premier émulateur lancé) -# ANDROID_HOME default: /opt/android-sdk -# (le SDK Android local; doit contenir -# emulator/emulator et platform-tools/adb) -# POSTIT_RID default: android-x64 -# (doit matcher l'ABI de l'AVD; `avdmanager list avd` -# affiche la ligne Tag/ABI) -# EMU_HEADLESS default: 0 -# (1 = lancer l'émulateur sans fenêtre, pour scripter) -# CONFIG surcharge la variable CONFIG globale (Debug par -# défaut dans ce Makefile). Passer à Release pour -# un APK optimisé et signé release. -# LOGCAT_LINES default: 200 -# (nombre de lignes dumpées par `make qemu-logcat`) -# LOGCAT_FOLLOW default: 0 -# (1 = stream live via `make logcat`, -# sinon dump one-shot des N dernières lignes) -# LOGCAT_BOOT_WAIT default: 30 -# (secondes d'attente entre le clear du buffer, -# le `am start`, et le dump final dans -# `make qemu-logcat-boot`) -AVD_NAME ?= postit_test_avd -ADB_SERIAL ?= emulator-5554 -ANDROID_HOME ?= /opt/android-sdk -POSTIT_RID ?= android-x64 -EMU_HEADLESS ?= 0 -LOGCAT_LINES ?= 600 -LOGCAT_FOLLOW ?= 0 -LOGCAT_BOOT_WAIT ?= 30 - -ANDROID_PACKAGE_NAME = fr.pschneider.postit -POSTIT_ANDROID_CSPROJ := src/PostIt/PostIt.Android/PostIt.Android.csproj -POSTIT_APK_DIR := src/PostIt/PostIt.Android/bin/$(CONFIG)/net10.0-android/$(POSTIT_RID) -POSTIT_APK := $(POSTIT_APK_DIR)/$(ANDROID_PACKAGE_NAME)-Signed.apk - -qemu-run: - @echo " Starting AVD $(AVD_NAME) on $(ADB_SERIAL)..." - @mkdir -p /tmp/yavsc-emu - @EMU_ARGS=""; \ - if [ "$(EMU_HEADLESS)" = "1" ]; then EMU_ARGS="-no-window -no-audio"; fi; \ - $(ANDROID_HOME)/emulator/emulator -avd $(AVD_NAME) $$EMU_ARGS \ - >/tmp/yavsc-emu/$(AVD_NAME).log 2>&1 & \ - echo " emulator PID: $$!" - -qemu-stop: - adb -s $(ADB_SERIAL) emu kill - -qemu-wait-boot: - @echo " Waiting for $(ADB_SERIAL) to finish booting..." - adb -s $(ADB_SERIAL) wait-for-device - @for i in $$(seq 1 180); do \ - BOOTED=$$(adb -s $(ADB_SERIAL) shell getprop sys.boot_completed 2>/dev/null | tr -d '\r\n'); \ - if [ "$$BOOTED" = "1" ]; then \ - echo " ✓ booted in $${i}s"; \ - exit 0; \ - fi; \ - sleep 1; \ - done; \ - echo " ERROR: device did not boot within 180s." >&2; \ - echo " Logs: /tmp/yavsc-emu/$(AVD_NAME).log" >&2; \ - exit 1 - -android-build: - # EmbedAssembliesIntoApk=true: without this, the Debug APK ships - # without the managed assemblies in it (they are pushed at runtime - # via `adb push`, "Fast Deployment"). On the qemu emulator, the - # runtime cannot find them in `files/.__override__//` and - # aborts at startup with "No assemblies found in '.__override__'" - # (monodroid-glue.cc:757, SIGABRT). Forcing this property on - # packages the .dlls into the APK as `assemblies//` so the - # runtime reads them directly. - # - # The Xamarin.Android SDK property is `EmbedAssembliesIntoApk`, - # not `AndroidEnableFastDeployment` (which exists in older - # templates but is a no-op in the .NET 10 SDK). - dotnet build $(POSTIT_ANDROID_CSPROJ) \ - -c $(CONFIG) \ - -p:RuntimeIdentifier=$(POSTIT_RID) \ - -p:EmbedAssembliesIntoApk=true \ - --nologo - @if [ ! -f "$(POSTIT_APK)" ]; then \ - echo " APK not found at $(POSTIT_APK)." >&2; \ - echo " Files in $(POSTIT_APK_DIR):" >&2; \ - ls -la "$(POSTIT_APK_DIR)" 2>/dev/null || echo " (directory does not exist)" >&2; \ - exit 1; \ - fi - - -android-install: android-build - @echo " Installing $(POSTIT_APK) on $(ADB_SERIAL)..." - adb -s $(ADB_SERIAL) install -r "$(POSTIT_APK)" -r - -qemu-uninstall: - adb -s $(ADB_SERIAL) uninstall $(ANDROID_PACKAGE_NAME) - -# Dump recent logcat output for the running PostIt.Android process. -# By default, prints the last $(LOGCAT_LINES) lines (one-shot, with -# `-d`). Set LOGCAT_FOLLOW=1 to follow the stream live instead. -# Filtering is by PID (pidof $(ANDROID_PACKAGE_NAME)), not by tag, -# because Mono/Xamarin can emit logs under several tags -# (mono, PostIt.Android, Avalonia.Android) and tag-based filtering -# would miss the ones not matching. PID-based filtering is exact. -# If the app is not running, pidof returns empty and logcat exits -# silently with no output; that is the expected behaviour for -# "no logs yet". -logcat: - @PID=$$(adb -s $(ADB_SERIAL) shell pidof $(ANDROID_PACKAGE_NAME) 2>/dev/null | tr -d '\r\n'); \ - if [ -z "$$PID" ]; then \ - echo " $(ANDROID_PACKAGE_NAME) is not running on $(ADB_SERIAL)."; \ - echo " Start the app first (am start -n $(ANDROID_PACKAGE_NAME)/PostIt.Android.PostItMainActivity)"; \ - exit 1; \ - fi; \ - echo " Following PID $$PID (LOGCAT_FOLLOW=$(LOGCAT_FOLLOW), LOGCAT_LINES=$(LOGCAT_LINES))"; \ - if [ "$(LOGCAT_FOLLOW)" = "1" ]; then \ - adb -s $(ADB_SERIAL) logcat -v time --pid=$$PID $(ANDROID_PACKAGE_NAME); \ - else \ - adb -s $(ADB_SERIAL) logcat -d -v time -t $(LOGCAT_LINES) --pid=$$PID $(ANDROID_PACKAGE_NAME); \ - fi - -# Clear logcat, launch PostIt.Android, then dump everything that was -# emitted during the startup window. Targets the "démarrage KO" case -# where the process starts but Avalonia never renders a frame — the -# logcat trace from process start to first frame is what diagnoses it. -# -# Override LOGCAT_BOOT_WAIT to extend the post-launch wait -# (default 15s; raise to 30+ if the device is slow to boot Avalonia). -LOGCAT_BOOT_WAIT ?= 15 - - -android-start: - @echo " Clearing logcat buffer..." - adb -s $(ADB_SERIAL) logcat -c - @echo " Launching $(ANDROID_PACKAGE_NAME)..." - adb -s $(ADB_SERIAL) shell am start \ - -n $(ANDROID_PACKAGE_NAME)/PostIt.Android.PostItMainActivity - -qemu-logcat-boot: android-start - @echo " Waiting $(LOGCAT_BOOT_WAIT)s for the app to start rendering..." - @sleep $(LOGCAT_BOOT_WAIT) - - @echo " Dumping logcat (PostIt PID + system buffer):" - @PID=$$(adb -s $(ADB_SERIAL) shell pidof $(ANDROID_PACKAGE_NAME) 2>/dev/null | tr -d '\r\n'); \ - if [ -n "$$PID" ]; then \ - echo " ✅ (PID $$PID at dump time)"; \ - sleep 10; \ - adb -s $(ADB_SERIAL) logcat -d -v time -t $(LOGCAT_LINES) --pid=$$PID; \ - else \ - echo " 👿 (PostIt process not running at dump time — dumping last $(LOGCAT_LINES) lines unfiltered)"; \ - adb -s $(ADB_SERIAL) logcat -d -v time -t $(LOGCAT_LINES); \ - exit 1; \ - fi - -qemu: qemu-run qemu-wait-boot android-install - @echo " ✓ PostIt.Android installed on $(ADB_SERIAL)" - -.PHONY: test release qemu qemu-run qemu-stop qemu-wait-boot android-build android-install logcat qemu-logcat-boot +.PHONY: test release diff --git a/src/PostIt/Makefile b/src/PostIt/Makefile index 72158bfa..1217976b 100644 --- a/src/PostIt/Makefile +++ b/src/PostIt/Makefile @@ -1,7 +1,178 @@ +# Cibles pour installer PostIt.Android en Debug sur l'AVD qemu. +# +# Usage typique : +# make qemu # lance l'AVD, attend le boot, build l'APK, l'installe +# make android-install # (re)build l'APK et l'installe (AVD doit tourner) +# make android-build # build l'APK seul (sans install) +# make qemu-run # démarre l'AVD en background +# make qemu-stop # arrête l'émulateur +# make qemu-wait-boot # attend que l'AVD ait fini de booter +# +# Variables surchargeables (make VAR=valeur) : +# AVD_NAME default: postit_test_avd +# (l'AVD doit être listé par `avdmanager list avd`) +# ADB_SERIAL default: emulator-5554 +# (port standard du premier émulateur lancé) +# ANDROID_HOME default: /opt/android-sdk +# (le SDK Android local; doit contenir +# emulator/emulator et platform-tools/adb) +# POSTIT_RID default: android-x64 +# (doit matcher l'ABI de l'AVD; `avdmanager list avd` +# affiche la ligne Tag/ABI) +# EMU_HEADLESS default: 0 +# (1 = lancer l'émulateur sans fenêtre, pour scripter) +# CONFIG surcharge la variable CONFIG globale (Debug par +# défaut dans ce Makefile). Passer à Release pour +# un APK optimisé et signé release. +# LOGCAT_LINES default: 200 +# (nombre de lignes dumpées par `make qemu-logcat`) +# LOGCAT_FOLLOW default: 0 +# (1 = stream live via `make logcat`, +# sinon dump one-shot des N dernières lignes) +# LOGCAT_BOOT_WAIT default: 30 +# (secondes d'attente entre le clear du buffer, +# le `am start`, et le dump final dans +# `make qemu-logcat-boot`) +AVD_NAME ?= postit_test_avd +ADB_SERIAL ?= emulator-5554 +ANDROID_HOME ?= /opt/android-sdk +POSTIT_RID ?= android-x64 +EMU_HEADLESS ?= 0 +LOGCAT_LINES ?= 600 +LOGCAT_FOLLOW ?= 0 +LOGCAT_BOOT_WAIT ?= 30 + +ANDROID_PACKAGE_NAME = fr.pschneider.postit +POSTIT_ANDROID_CSPROJ := PostIt.Android/PostIt.Android.csproj +POSTIT_APK_DIR := PostIt.Android/bin/$(CONFIG)/net10.0-android/$(POSTIT_RID) +POSTIT_APK := $(POSTIT_APK_DIR)/$(ANDROID_PACKAGE_NAME)-Signed.apk + clean: clean-PostIt clean-PostIt.Android clean-PostIt.Desktop clean-%: rm -rf $*/obj $*/bin -.PHONY: clean +qemu-run: + @echo " Starting AVD $(AVD_NAME) on $(ADB_SERIAL)..." + @mkdir -p /tmp/yavsc-emu + @EMU_ARGS=""; \ + if [ "$(EMU_HEADLESS)" = "1" ]; then EMU_ARGS="-no-window -no-audio"; fi; \ + $(ANDROID_HOME)/emulator/emulator -avd $(AVD_NAME) $$EMU_ARGS \ + >/tmp/yavsc-emu/$(AVD_NAME).log 2>&1 & \ + echo " ✅ Started emulator PID: $$!" + +qemu-stop: + adb -s $(ADB_SERIAL) emu kill + echo " ✅ Stopped emulator" + +qemu-wait-boot: + @echo " Waiting for $(ADB_SERIAL) to finish booting..." + adb -s $(ADB_SERIAL) wait-for-device + @for i in $$(seq 1 180); do \ + BOOTED=$$(adb -s $(ADB_SERIAL) shell getprop sys.boot_completed 2>/dev/null | tr -d '\r\n'); \ + if [ "$$BOOTED" = "1" ]; then \ + echo " ✓ booted in $${i}s"; \ + exit 0; \ + fi; \ + sleep 1; \ + done; \ + echo " 👿 ERROR: device did not boot within 180s." >&2; \ + echo " Logs: /tmp/yavsc-emu/$(AVD_NAME).log" >&2; \ + exit 1 + +android-build: + # EmbedAssembliesIntoApk=true: without this, the Debug APK ships + # without the managed assemblies in it (they are pushed at runtime + # via `adb push`, "Fast Deployment"). On the qemu emulator, the + # runtime cannot find them in `files/.__override__//` and + # aborts at startup with "No assemblies found in '.__override__'" + # (monodroid-glue.cc:757, SIGABRT). Forcing this property on + # packages the .dlls into the APK as `assemblies//` so the + # runtime reads them directly. + # + # The Xamarin.Android SDK property is `EmbedAssembliesIntoApk`, + # not `AndroidEnableFastDeployment` (which exists in older + # templates but is a no-op in the .NET 10 SDK). + dotnet build $(POSTIT_ANDROID_CSPROJ) \ + -c $(CONFIG) \ + -p:RuntimeIdentifier=$(POSTIT_RID) \ + -p:EmbedAssembliesIntoApk=true \ + --nologo + @if [ ! -f "$(POSTIT_APK)" ]; then \ + echo " APK not found at $(POSTIT_APK)." >&2; \ + echo " Files in $(POSTIT_APK_DIR):" >&2; \ + ls -la "$(POSTIT_APK_DIR)" 2>/dev/null || echo " (directory does not exist)" >&2; \ + exit 1; \ + fi + + +android-install: android-build + @echo " Installing $(POSTIT_APK) on $(ADB_SERIAL)..." + adb -s $(ADB_SERIAL) install -r "$(POSTIT_APK)" -r + @echo " ✅ PostIt.Android installed on $(ADB_SERIAL)" + +qemu-uninstall: + adb -s $(ADB_SERIAL) uninstall $(ANDROID_PACKAGE_NAME) + +# Dump recent logcat output for the running PostIt.Android process. +# By default, prints the last $(LOGCAT_LINES) lines (one-shot, with +# `-d`). Set LOGCAT_FOLLOW=1 to follow the stream live instead. +# Filtering is by PID (pidof $(ANDROID_PACKAGE_NAME)), not by tag, +# because Mono/Xamarin can emit logs under several tags +# (mono, PostIt.Android, Avalonia.Android) and tag-based filtering +# would miss the ones not matching. PID-based filtering is exact. +# If the app is not running, pidof returns empty and logcat exits +# silently with no output; that is the expected behaviour for +# "no logs yet". +logcat: + @PID=$$(adb -s $(ADB_SERIAL) shell pidof $(ANDROID_PACKAGE_NAME) 2>/dev/null | tr -d '\r\n'); \ + if [ -z "$$PID" ]; then \ + echo " $(ANDROID_PACKAGE_NAME) is not running on $(ADB_SERIAL)."; \ + echo " Start the app first (am start -n $(ANDROID_PACKAGE_NAME)/PostIt.Android.PostItMainActivity)"; \ + exit 1; \ + fi; \ + echo " Following PID $$PID (LOGCAT_FOLLOW=$(LOGCAT_FOLLOW), LOGCAT_LINES=$(LOGCAT_LINES))"; \ + if [ "$(LOGCAT_FOLLOW)" = "1" ]; then \ + adb -s $(ADB_SERIAL) logcat -v time --pid=$$PID $(ANDROID_PACKAGE_NAME); \ + else \ + adb -s $(ADB_SERIAL) logcat -d -v time -t $(LOGCAT_LINES) --pid=$$PID $(ANDROID_PACKAGE_NAME); \ + fi + +# Clear logcat, launch PostIt.Android, then dump everything that was +# emitted during the startup window. Targets the "démarrage KO" case +# where the process starts but Avalonia never renders a frame — the +# logcat trace from process start to first frame is what diagnoses it. +# +# Override LOGCAT_BOOT_WAIT to extend the post-launch wait +# (default 15s; raise to 30+ if the device is slow to boot Avalonia). +LOGCAT_BOOT_WAIT ?= 15 + + +android-start: + @echo " Clearing logcat buffer..." + adb -s $(ADB_SERIAL) logcat -c + @echo " Launching $(ANDROID_PACKAGE_NAME)..." + adb -s $(ADB_SERIAL) shell am start \ + -n $(ANDROID_PACKAGE_NAME)/PostIt.Android.PostItMainActivity + @echo " ✅ $(ANDROID_PACKAGE_NAME) started on $(ADB_SERIAL)" + +qemu-logcat-boot: android-start + @echo " Waiting $(LOGCAT_BOOT_WAIT)s for the app to start rendering..." + @sleep $(LOGCAT_BOOT_WAIT) + + @echo " Dumping logcat (PostIt PID + system buffer):" + @PID=$$(adb -s $(ADB_SERIAL) shell pidof $(ANDROID_PACKAGE_NAME) 2>/dev/null | tr -d '\r\n'); \ + if [ -n "$$PID" ]; then \ + echo " ✅ (PID $$PID at dump time)"; \ + sleep 10; \ + adb -s $(ADB_SERIAL) logcat -d -v time -t $(LOGCAT_LINES) --pid=$$PID; \ + else \ + echo " 👿 (PostIt process not running at dump time — dumping last $(LOGCAT_LINES) lines unfiltered)"; \ + adb -s $(ADB_SERIAL) logcat -d -v time -t $(LOGCAT_LINES); \ + exit 1; \ + fi + +qemu: qemu-run qemu-wait-boot android-install + +.PHONY: clean qemu qemu-run qemu-stop qemu-wait-boot android-build android-install logcat qemu-logcat-boot diff --git a/src/PostIt/PostIt/App.axaml.cs b/src/PostIt/PostIt/App.axaml.cs index 67d6dac2..f8430347 100644 --- a/src/PostIt/PostIt/App.axaml.cs +++ b/src/PostIt/PostIt/App.axaml.cs @@ -44,27 +44,15 @@ public partial class App : Application this.ServiceProvider = new ServiceCollection().BuildServices(); var settings = ServiceProvider.GetRequiredService(); - var sessionStatus = ServiceProvider!.GetRequiredService(); - sessionStatus.LogoutCompleted += () => - { - View.NavRoot.PopToRootAsync(); - }; - sessionStatus.LoginSucceeded += () => - { - PushMainPageAsync(); - }; if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { var window = ServiceProvider.GetRequiredService(); desktop.MainWindow = window; var api = ServiceProvider!.GetRequiredService(); desktop.MainWindow.Opened += async (_, _) => await BootAsync(this.ServiceProvider!, api); - View = window.MainView; - - View.SessionBanner.DataContext = sessionStatus; - // FIXME Window.Opened += async (_, _) => await BootAsync(this.ServiceProvider!, api); + this.ConfigureRootView(window.MainView); ApplyDarkMode(settings); } @@ -74,15 +62,15 @@ public partial class App : Application () => { View = ServiceProvider.GetRequiredService(); + this.ConfigureRootView(View); ApplyDarkMode(settings); - View.SessionBanner.DataContext = sessionStatus; return View; }; } else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform) { singleViewPlatform.MainView = View = ServiceProvider.GetRequiredService(); - View.SessionBanner.DataContext = sessionStatus; + ConfigureRootView(View); ApplyDarkMode(settings); } var mainVm = ServiceProvider!.GetRequiredService(); @@ -91,6 +79,27 @@ public partial class App : Application this.PushPageAsync(mainVm); } +private void ConfigureRootView(MainView rootView) +{ + var api = ServiceProvider!.GetRequiredService(); + + // Déclencher le Boot lors du chargement du contrôle à l'écran + rootView.AttachedToVisualTree += async (_, _) => await BootAsync(this.ServiceProvider!, api); + + var sessionStatus = ServiceProvider!.GetRequiredService(); + sessionStatus.LogoutCompleted += () => + { + // Remplacer Window.NavRoot par rootView.NavRoot + rootView.NavRoot.PopToRootAsync(); + }; + + sessionStatus.LoginSucceeded += () => + { + PushMainPageAsync(); + }; + + rootView.SessionBanner.DataContext = sessionStatus; +} /// /// Test-only hook: bind a concrete so From 75b298b0f80c1c1768290c248efdbb810025004c Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 25 Aug 2026 19:20:03 +0100 Subject: [PATCH 14/73] Fixes the Android Login process --- .vscode/launch.json | 14 +++---- .vscode/settings.json | 2 + .vscode/tasks.json | 4 +- src/PostIt/PostIt.Android/MainActivity.cs | 16 +++++--- .../PostIt.Android/PlatformBootstrap.cs | 7 +--- .../Properties/AndroidManifest.xml | 26 ------------- .../Services/AndroidSystemBrowser.cs | 10 ++++- .../Services/OidcCallbackManager.cs | 21 ++++++++++ .../WebAuthenticationCallbackActivity.cs | 35 +++++++++++++++++ .../PostIt.Desktop/PlatformBootstrap.cs | 29 -------------- src/PostIt/PostIt.Desktop/Program.cs | 2 - src/PostIt/PostIt.Tests/SettingsLoadTests.cs | 2 +- src/PostIt/PostIt/App.axaml.cs | 10 ++--- src/PostIt/PostIt/Services/Platform.cs | 6 +-- .../PostIt/Settings/AuthenticationSettings.cs | 12 ++++-- src/PostIt/PostIt/ViewModels/Settings.cs | 39 ++----------------- 16 files changed, 106 insertions(+), 129 deletions(-) create mode 100644 src/PostIt/PostIt.Android/Services/OidcCallbackManager.cs create mode 100644 src/PostIt/PostIt.Android/WebAuthenticationCallbackActivity.cs delete mode 100644 src/PostIt/PostIt.Desktop/PlatformBootstrap.cs diff --git a/.vscode/launch.json b/.vscode/launch.json index 36dc17a2..dc8d3c68 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,19 +5,19 @@ "version": "0.2.0", "configurations": [ { - "name": "Android", + "name": "Android Debug", "type": "mono", "preLaunchTask": "run-debug-android", "request": "attach", "address": "localhost", - "port": 10000 + "port": 55555 }, { - "name": "Attach - Android", + "name": "Android Attach - Debug", "type": "mono", "request": "attach", "address": "localhost", - "port": 10000 + "port": 55555 }, { "name": "API", @@ -26,19 +26,19 @@ "projectPath": "${workspaceFolder}/src/Api/Api.csproj" }, { - "name": "Yavsc.Org", + "name": "Yavsc Org", "type": "dotnet", "request": "launch", "projectPath": "${workspaceFolder}/src/Yavsc.Org/Yavsc.Org.csproj", }, { - "name": "Yavsc.Blogs", + "name": "Yavsc Blogs", "type": "dotnet", "request": "launch", "projectPath": "${workspaceFolder}/src/Yavsc.Blogs/Yavsc.Blogs.csproj" }, { - "name": "PostIt", + "name": "PostIt Desktop", "type": "dotnet", "request": "launch", "projectPath": "${workspaceFolder}/src/PostIt/PostIt.Desktop/PostIt.Desktop.csproj", diff --git a/.vscode/settings.json b/.vscode/settings.json index 16bbe483..915683fc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,6 +5,7 @@ "appsettings", "asciidoctor", "ASPNETCORE", + "Avalonia", "Configurabilité", "Cratie", "DESTDIR", @@ -15,6 +16,7 @@ "Hsts", "Newtonsoft", "Npgsql", + "Oidc", "PKCE", "postit", "pschneider", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 9fe9caaf..3c0c0bf2 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -18,8 +18,8 @@ "-p:TargetFramework=net10.0-android", "-p:Configuration=Debug", "-p:AndroidAttachDebugger=true", - "-p:AndroidSdbHostPort=10000", - "-p:AndroidSdbTargetPort=10000" + "-p:AndroidSdbHostPort=55555", + "-p:AndroidSdbTargetPort=55555" ], "problemMatcher": [ { diff --git a/src/PostIt/PostIt.Android/MainActivity.cs b/src/PostIt/PostIt.Android/MainActivity.cs index 4f788550..ad8455ef 100644 --- a/src/PostIt/PostIt.Android/MainActivity.cs +++ b/src/PostIt/PostIt.Android/MainActivity.cs @@ -1,13 +1,11 @@ -using Android; + using Android.App; using Android.Content; using Android.Content.PM; using AndroidX.Core.Provider; using AndroidX.Emoji2.Text; -using Avalonia; using Avalonia.Android; -using AndroidX.Core.Provider; -using AndroidX.Emoji2.Text; +using PostIt.Droid.Services; namespace PostIt.Android; @@ -34,7 +32,7 @@ public class MainActivity : AvaloniaMainActivity Yavsc.Resource.Array.com_google_android_gms_fonts_certs); //com_google_android_gms_fonts_certs EmojiCompat.Config config = new FontRequestEmojiCompatConfig(this, fontRequest); EmojiCompat.Init(config); - PlatformBootstrap.EnsureInitialized(); + PlatformBootstrap.InitPlatform(); base.OnCreate(savedInstanceState); Current = this; } @@ -50,7 +48,13 @@ public class MainActivity : AvaloniaMainActivity protected override void OnNewIntent(Intent? intent) { base.OnNewIntent(intent); - if (intent is not null) AndroidOidcCallbackSink.Handle(intent); + + var url = intent?.DataString; + if (!string.IsNullOrEmpty(url) && url.StartsWith("postit://callback")) + { + OidcCallbackManager.SetResult(url); + } + } internal static class AndroidOidcCallbackSink diff --git a/src/PostIt/PostIt.Android/PlatformBootstrap.cs b/src/PostIt/PostIt.Android/PlatformBootstrap.cs index d59b154f..f208f9ce 100644 --- a/src/PostIt/PostIt.Android/PlatformBootstrap.cs +++ b/src/PostIt/PostIt.Android/PlatformBootstrap.cs @@ -12,14 +12,9 @@ namespace PostIt.Android; /// internal static class PlatformBootstrap { - private static int _initialized; - - internal static void EnsureInitialized() + internal static void InitPlatform() { - if (System.Threading.Interlocked.Exchange(ref _initialized, 1) != 0) - return; - Platform.DefaultRedirectUri = ViewModels.Settings.AndroidRedirectUri; Platform.CreateBrowser = () => { var activity = MainActivity.Current; diff --git a/src/PostIt/PostIt.Android/Properties/AndroidManifest.xml b/src/PostIt/PostIt.Android/Properties/AndroidManifest.xml index 91b61d05..8793aae8 100644 --- a/src/PostIt/PostIt.Android/Properties/AndroidManifest.xml +++ b/src/PostIt/PostIt.Android/Properties/AndroidManifest.xml @@ -2,31 +2,5 @@ - - - - - - - - - - diff --git a/src/PostIt/PostIt.Android/Services/AndroidSystemBrowser.cs b/src/PostIt/PostIt.Android/Services/AndroidSystemBrowser.cs index b6716e22..bb10b364 100644 --- a/src/PostIt/PostIt.Android/Services/AndroidSystemBrowser.cs +++ b/src/PostIt/PostIt.Android/Services/AndroidSystemBrowser.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Android.App; using AndroidX.Browser.CustomTabs; using IdentityModel.OidcClient.Browser; +using PostIt.Droid.Services; namespace PostIt.Android.Services; @@ -35,9 +36,14 @@ public sealed class AndroidSystemBrowser : IBrowser }; } - var uri = global::Android.Net.Uri.Parse(options.StartUrl)!; + // 1. Enregistrez la tâche avant de lancer le Custom Tab + var callbackTask = OidcCallbackManager.RegisterCallback(cancellationToken); - var callbackTask = MainActivity.AndroidOidcCallbackSink.AwaitNextCallbackAsync(); + // 2. LANCEZ VOTRE CUSTOM TAB ICI (via AndroidX.Browser.CustomTabs) + // ... code pour ouvrir l'URL d'authentification ... + + + var uri = global::Android.Net.Uri.Parse(options.StartUrl)!; var tabsIntent = new CustomTabsIntent.Builder() .SetShowTitle(true)! diff --git a/src/PostIt/PostIt.Android/Services/OidcCallbackManager.cs b/src/PostIt/PostIt.Android/Services/OidcCallbackManager.cs new file mode 100644 index 00000000..30f8fa18 --- /dev/null +++ b/src/PostIt/PostIt.Android/Services/OidcCallbackManager.cs @@ -0,0 +1,21 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace PostIt.Droid.Services; + +public static class OidcCallbackManager +{ + private static TaskCompletionSource? _tcs; + + public static Task RegisterCallback(CancellationToken cancellationToken) + { + _tcs = new TaskCompletionSource(); + cancellationToken.Register(() => _tcs.TrySetCanceled()); + return _tcs.Task; + } + + public static void SetResult(string url) + { + _tcs?.TrySetResult(url); + } +} diff --git a/src/PostIt/PostIt.Android/WebAuthenticationCallbackActivity.cs b/src/PostIt/PostIt.Android/WebAuthenticationCallbackActivity.cs new file mode 100644 index 00000000..9ed2eb18 --- /dev/null +++ b/src/PostIt/PostIt.Android/WebAuthenticationCallbackActivity.cs @@ -0,0 +1,35 @@ +using Android.App; +using Android.Content; +using Android.Content.PM; +using Android.OS; +using PostIt.Droid.Services; + +namespace PostIt.Android; + +[Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop, Exported = true)] +[IntentFilter(new[] { Intent.ActionView }, + Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable }, + DataScheme = "postit", // Remplacez par votre schéma personnalisé (ex: yavsc ou postit) + DataHost = "callback")] // Correspond à postit://callback +public class WebAuthenticationCallbackActivity : Activity +{ + protected override void OnCreate(Bundle? savedInstanceState) + { + base.OnCreate(savedInstanceState); + + // Capturer l'URL de redirection OIDC + var url = Intent?.DataString; + + if (!string.IsNullOrEmpty(url)) + { + // Transmettre l'URL au gestionnaire partagé pour compléter la Task + OidcCallbackManager.SetResult(url); + } + + // Fermer cette activité transparente et ramener l'application au premier plan + var intent = new Intent(this, typeof(MainActivity)); + intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop); + StartActivity(intent); + Finish(); + } +} diff --git a/src/PostIt/PostIt.Desktop/PlatformBootstrap.cs b/src/PostIt/PostIt.Desktop/PlatformBootstrap.cs deleted file mode 100644 index ff9ca7f6..00000000 --- a/src/PostIt/PostIt.Desktop/PlatformBootstrap.cs +++ /dev/null @@ -1,29 +0,0 @@ -using PostIt.Services; - -namespace PostIt.Desktop; - -/// -/// One-shot platform bootstrap. Called from Program.Main so that -/// the shared OIDC login path sees a working IBrowser — the -/// custom-scheme browser that hands the OIDC callback off to the -/// running instance through the named pipe. Desktop builds do NOT use -/// a loopback HTTP listener: the postit:// scheme is registered -/// with the OS at install time and the browser is whatever the user -/// has configured to open it. -/// -internal static class PlatformBootstrap -{ - private static int _initialized; - - internal static void EnsureInitialized() - { - if (System.Threading.Interlocked.Exchange(ref _initialized, 1) != 0) - return; - - // Use the custom-scheme redirect on Desktop. Loopback is only - // a fallback for platforms that cannot register postit:// - // (see Settings.DefaultLoopbackRedirectUri for that path). - Platform.DefaultRedirectUri = AuthenticationSettings.DefaultDesktopRedirectUri; - Platform.CustomScheme = "postit"; - } -} diff --git a/src/PostIt/PostIt.Desktop/Program.cs b/src/PostIt/PostIt.Desktop/Program.cs index f22f79b0..0de3bd69 100644 --- a/src/PostIt/PostIt.Desktop/Program.cs +++ b/src/PostIt/PostIt.Desktop/Program.cs @@ -12,8 +12,6 @@ sealed class Program [STAThread] public static void Main(string[] args) { - PlatformBootstrap.EnsureInitialized(); - // Short-circuit 2nd-instance launches (OS handing us the // postit://callback URL) BEFORE Avalonia spins up a window. // If we let Avalonia initialise, the new MainWindow flashes diff --git a/src/PostIt/PostIt.Tests/SettingsLoadTests.cs b/src/PostIt/PostIt.Tests/SettingsLoadTests.cs index dc58e9fc..43021caa 100644 --- a/src/PostIt/PostIt.Tests/SettingsLoadTests.cs +++ b/src/PostIt/PostIt.Tests/SettingsLoadTests.cs @@ -85,7 +85,7 @@ public class SettingsLoadTests bool flip = ((workerId + i) & 1) == 0; settings.DarkMode = flip; settings.Authentication.RedirectUri = - global::AuthenticationSettings.DefaultDesktopRedirectUri; + global::AuthenticationSettings.DesktopRedirectUri; settings.BusinessApiUrl = flip ? "https://a.example.test/api/v1/" diff --git a/src/PostIt/PostIt/App.axaml.cs b/src/PostIt/PostIt/App.axaml.cs index f8430347..1b019f6e 100644 --- a/src/PostIt/PostIt/App.axaml.cs +++ b/src/PostIt/PostIt/App.axaml.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Threading.Tasks; using Avalonia; using Avalonia.Controls; @@ -73,10 +72,8 @@ public partial class App : Application ConfigureRootView(View); ApplyDarkMode(settings); } - var mainVm = ServiceProvider!.GetRequiredService(); base.OnFrameworkInitializationCompleted(); - this.PushPageAsync(mainVm); } private void ConfigureRootView(MainView rootView) @@ -93,9 +90,9 @@ private void ConfigureRootView(MainView rootView) rootView.NavRoot.PopToRootAsync(); }; - sessionStatus.LoginSucceeded += () => + sessionStatus.LoginSucceeded += async () => { - PushMainPageAsync(); + await PushMainPageAsync(); }; rootView.SessionBanner.DataContext = sessionStatus; @@ -133,6 +130,9 @@ private void ConfigureRootView(MainView rootView) var refreshed = await api.TrySilentLoginAsync().ConfigureAwait(true); var sessionStatus = provider.GetRequiredService(); sessionStatus.Refresh(); + var homePage = provider.GetRequiredService(); + var app = (App)Current!; + await app.PushPageAsync(homePage); if (!refreshed) return; await PushMainPageAsync().ConfigureAwait(true); diff --git a/src/PostIt/PostIt/Services/Platform.cs b/src/PostIt/PostIt/Services/Platform.cs index c867c63c..8e5f7e25 100644 --- a/src/PostIt/PostIt/Services/Platform.cs +++ b/src/PostIt/PostIt/Services/Platform.cs @@ -21,14 +21,14 @@ public static class Platform /// override this property at startup (e.g. PostIt.Android sets /// it to android://postit-signin). /// - public static string DefaultRedirectUri { get; set; } = "postit://callback"; + public const string RedirectUri = "postit://callback"; /// /// Scheme prefix the matches /// against BrowserOptions.EndUrl. Overridable for apps /// that want to register their own scheme. /// - public static string CustomScheme { get; set; } = "postit"; + public const string CustomScheme = "postit"; /// /// Constructs a fresh for the running platform. @@ -37,4 +37,4 @@ public static class Platform /// public static System.Func? CreateBrowser { get; set; } = () => new CustomSchemeBrowser(CustomScheme); -} \ No newline at end of file +} diff --git a/src/PostIt/PostIt/Settings/AuthenticationSettings.cs b/src/PostIt/PostIt/Settings/AuthenticationSettings.cs index 99358cfb..9ebeaebd 100644 --- a/src/PostIt/PostIt/Settings/AuthenticationSettings.cs +++ b/src/PostIt/PostIt/Settings/AuthenticationSettings.cs @@ -10,7 +10,7 @@ public partial class AuthenticationSettings : ObservableObject /// hand-off in /// (RFC 8252 §7.1). Production Desktop builds use this. /// - public const string DefaultDesktopRedirectUri = "postit://callback"; + public const string DesktopRedirectUri = "postit://callback"; /// /// Redirect URI used by the Android app. The corresponding IntentFilter @@ -34,15 +34,19 @@ public partial class AuthenticationSettings : ObservableObject [ObservableProperty] public partial string[] Scopes { get; set; } - /// - /// OAuth redirect URI. Defaults to + /// OAuth redirect URI. Defaults to /// (custom URI scheme) which is the right answer for desktop /// production builds. Mobile platforms must set this to /// before calling LoginAsync. /// [ObservableProperty] - public partial string RedirectUri { get; set; } = DefaultDesktopRedirectUri; + public partial string RedirectUri { get; set; } +#if ANDROID + = AndroidRedirectUri; +#else + = DesktopRedirectUri; +#endif /// /// Space-separated view of . Exists for the diff --git a/src/PostIt/PostIt/ViewModels/Settings.cs b/src/PostIt/PostIt/ViewModels/Settings.cs index 2115a0cd..fd87d772 100644 --- a/src/PostIt/PostIt/ViewModels/Settings.cs +++ b/src/PostIt/PostIt/ViewModels/Settings.cs @@ -2,13 +2,11 @@ using System.Runtime.CompilerServices; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using IdentityModel.OidcClient; -using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Text.Json; -using System.Threading; [assembly: InternalsVisibleTo("PostIt.Tests")] @@ -18,37 +16,6 @@ public partial class Settings : ViewModelBase { const string SettingsFileName = "postit-settings.json"; - /// - /// Redirect URI used by the Android app. The corresponding IntentFilter - /// in PostIt.Android/Properties/AndroidManifest.xml must match. - /// - public const string AndroidRedirectUri = "android://postit-signin"; - - - - /// - /// Process-wide canonical instance, wired up - /// at application boot by - /// through . The hybrid pattern: - /// - /// The static Current reference gives - /// ViewModels a non-DI way to reach the same instance (and lets - /// the framework bindings push notifications through one stable - /// ). - /// Tests that want to exercise a clean - /// instance still call new Settings(); Current - /// stays null in those contexts because - /// is never invoked. - /// Reads () are - /// thread-safe and never allocate; mutations always go through - /// the DI-resolved singleton so two threads cannot each register - /// a different "current" Settings. - /// - /// - private static Settings? s_current; - - - [ObservableProperty] public partial AuthenticationSettings Authentication { get; set; } = new(); @@ -66,7 +33,7 @@ public partial class Settings : ViewModelBase /// setters above all funnel through here, and we flip /// in lock-step. Sub-property mutations /// (e.g. Authentication.Authority) are caught by the - /// subscription wired up in + /// subscription wired up in /// below. disables the flag during bulk /// hydration so the disk load itself does not count as a user /// edit. @@ -336,7 +303,7 @@ public partial class Settings : ViewModelBase this.Authentication.ClientId = string.IsNullOrWhiteSpace(settings.Authentication.ClientId) ? AuthenticationSettings.DefaultClientId : settings.Authentication.ClientId; this.Authentication.RedirectUri = string.IsNullOrWhiteSpace(settings.Authentication.RedirectUri) ? - AuthenticationSettings.DefaultDesktopRedirectUri : settings.Authentication.RedirectUri; + AuthenticationSettings.DesktopRedirectUri : settings.Authentication.RedirectUri; if (settings.Authentication.Scopes is null || settings.Authentication.Scopes.Length == 0) { settings.Authentication.Scopes = AuthenticationSettings.DefaultScopes; @@ -377,7 +344,7 @@ public partial class Settings : ViewModelBase { Authority = AuthenticationSettings.DefaultAuthority, ClientId = AuthenticationSettings.DefaultClientId, - RedirectUri = AuthenticationSettings.DefaultDesktopRedirectUri, + RedirectUri = AuthenticationSettings.DesktopRedirectUri, Scopes = AuthenticationSettings.DefaultScopes }; this.DarkMode = false; From c707b5f29edb6e2b607033a8e9e0683f6b4cc680 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 25 Aug 2026 19:26:52 +0100 Subject: [PATCH 15/73] Release 1.0.8-rc3 - unstable --- .forgejo/workflows/release.yml | 2 +- CHANGELOG.md | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index 09d9757a..d7b12d2e 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -197,7 +197,7 @@ jobs: APK=src/PostIt/PostIt.Android/bin/Release/net10.0-android/android-arm64/fr.pschneider.PostIt-Signed.apk if [[ ! -f "$APK" ]]; then echo "::error::APK not found at $APK" - ls -la src/PostIt/PostIt.Android/bin/Release/net10.0-android/ 2>/dev/null || true + ls -la src/PostIt/PostIt.Android/bin/Release/net10.0-android/android-arm64 2>/dev/null || true exit 1 fi cp "$APK" /src/_src/PostIt.Android.apk diff --git a/CHANGELOG.md b/CHANGELOG.md index 73a4a88f..acb3c275 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,16 +21,17 @@ pour la production des paquets `.deb`. ### Added * a code cleanup -* a failling a disabled test ala Xamarin.UITest : the Android app stil doesn't starts -- Android app does not crash any more, but still no home page, only the splash screnn +* a first Xamarin.UITest is successful +* Android app starts, the login process succeeds ### Changed -mostly nothing +mostly nothing but refactorings ### Fixed -mostly nothing +nothing, [TODO] a bug persists laoding a blog post from PostIt, ACL sould come along with and should not need any "Refresh" button. +Today, assigning ACL succeeds the first time, the following times result in a 409 ## [1.0.8-rc1] - unstable From 6d6c4f2a8a0882e21cc36adaed3ebd51bcac894f Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 25 Aug 2026 20:30:39 +0100 Subject: [PATCH 16/73] Package renamed impact --- .forgejo/workflows/release.yml | 2 +- .github/workflows/docker-publish-android.yml | 2 +- src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index d7b12d2e..cf6594ec 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -194,7 +194,7 @@ jobs: # la racine du checkout pour que l'étape d'upload le trouve. run: | cd /src/_src - APK=src/PostIt/PostIt.Android/bin/Release/net10.0-android/android-arm64/fr.pschneider.PostIt-Signed.apk + APK=src/PostIt/PostIt.Android/bin/Release/net10.0-android/android-arm64/fr.pschneider.postit-Signed.apk if [[ ! -f "$APK" ]]; then echo "::error::APK not found at $APK" ls -la src/PostIt/PostIt.Android/bin/Release/net10.0-android/android-arm64 2>/dev/null || true diff --git a/.github/workflows/docker-publish-android.yml b/.github/workflows/docker-publish-android.yml index d560b216..a4ce15aa 100644 --- a/.github/workflows/docker-publish-android.yml +++ b/.github/workflows/docker-publish-android.yml @@ -40,7 +40,7 @@ jobs: - name: Extraire l'APK du conteneur Docker run: | docker create --name extractor postit-android - docker cp extractor:/src/src/PostIt/PostIt.Android/bin/Release/net10.0-android/android-arm64/fr.pschneider.PostIt-Signed.apk ./PostIt.Android.apk + docker cp extractor:/src/src/PostIt/PostIt.Android/bin/Release/net10.0-android/android-arm64/fr.pschneider.postit-Signed.apk ./PostIt.Android.apk docker rm extractor - name: Téléverser l'APK en tant qu'Artéfact GitHub diff --git a/src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs b/src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs index 23b423e1..8a256afc 100644 --- a/src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs +++ b/src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs @@ -14,7 +14,7 @@ namespace PostIt.Tests; /// public class AndroidAppLaunchTests { - private const string PackageName = "fr.pschneider.PostIt"; + private const string PackageName = "fr.pschneider.postit"; private readonly ITestOutputHelper _output; From 50a07102cbe17e2a617fd294f1ae54ad393a3109 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 25 Aug 2026 21:15:04 +0100 Subject: [PATCH 17/73] Do not fail at attaching developer tools --- src/PostIt/PostIt/App.axaml.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/PostIt/PostIt/App.axaml.cs b/src/PostIt/PostIt/App.axaml.cs index 1b019f6e..c4db01c4 100644 --- a/src/PostIt/PostIt/App.axaml.cs +++ b/src/PostIt/PostIt/App.axaml.cs @@ -33,7 +33,14 @@ public partial class App : Application { AvaloniaXamlLoader.Load(this); #if DEBUG - this.AttachDeveloperTools(); + try { + this.AttachDeveloperTools(); + } + catch (Exception ex) + { + Console.Error.WriteLine( + $"Could not attache developer tools : {ex.Message}"); + } #endif } From d56ad25e6b36985a26f1e27f69b53b55705b05e6 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 25 Aug 2026 23:01:00 +0100 Subject: [PATCH 18/73] fixes the tests --- .forgejo/workflows/buildAndTest.yml | 25 ++++++++++ .../PostIt.Tests/SessionStatusBannerTests.cs | 48 +++++++++++-------- src/PostIt/PostIt/App.axaml.cs | 14 +----- 3 files changed, 54 insertions(+), 33 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index a0f3a375..7bfc0c8b 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -27,6 +27,9 @@ jobs: build: runs-on: docker + container: + # Options cruciales pour donner accès à KVM et autoriser l'émulation + options: --device /dev/kvm --privileged steps: - name: Clone yavsc @@ -44,5 +47,27 @@ jobs: run: cd /src/_src && dotnet restore - name: Build run: cd /src/_src && dotnet build --no-restore + - name: Démarrer l'émulateur QEMU Headless et exécuter les tests + run: | + echo "Démarrage de l'émulateur en tâche de fond..." + # Remplacer 'pixel_5_api_30' par le nom exact de votre AVD créé sur l'hôte + emulator -avd emulator-5554 -no-window -no-audio -no-boot-anim -gpu swiftshader & + EMU_PID=$! + echo "Attente de la détection par ADB..." + adb wait-for-device + echo "Attente de la fin du boot d'Android..." + OUT="" + while [[ "$OUT" != "1" ]]; do + sleep 5 + OUT=$(adb shell getprop sys.boot_completed | tr -d '\r') + echo "Statut actuel : ${OUT:-0}" + done + echo "✅ L'émulateur Android est prêt !" + echo "Installation de l'APK de Debug..." + adb install /src/_src/src/PostIt/PostIt.Android/bin/Debug/net10.0-android/fr.pschneider.postit-Signed.apk + dotnet test /src/_src/src/PostIt/PostIt.Tests/PostIt.Tests.csproj -c Release + - name: Test + echo "⌛ Lancement des tests ..." run: cd /src/_src && dotnet test --no-build --verbosity normal + diff --git a/src/PostIt/PostIt.Tests/SessionStatusBannerTests.cs b/src/PostIt/PostIt.Tests/SessionStatusBannerTests.cs index 0a28ee87..4d49b865 100644 --- a/src/PostIt/PostIt.Tests/SessionStatusBannerTests.cs +++ b/src/PostIt/PostIt.Tests/SessionStatusBannerTests.cs @@ -34,10 +34,10 @@ public class SessionStatusBannerTests [AvaloniaFact] public void Banner_renders_three_buttons_in_the_visual_tree() { - var window = new MainView(); - window.SessionBanner.DataContext = new SessionStatusViewModel(); + MainWindow window = new MainWindow(); + window.Show(); - var buttons = window.SessionBanner.GetVisualDescendants() + var buttons = window.GetVisualDescendants() .OfType - internal void AttachMainWindow(MainView mainWindow) + internal void AttachMainWindow(MainView mainView) { - View = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); + View = mainView ?? throw new ArgumentNullException(nameof(mainView)); } private static void ApplyDarkMode(Settings settings) From b18f86ed230dc892f1581c91e8338ff5f31de7d4 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 25 Aug 2026 23:06:25 +0100 Subject: [PATCH 19/73] fixes the script --- .forgejo/workflows/buildAndTest.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 7bfc0c8b..a3f63cef 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -63,11 +63,11 @@ jobs: echo "Statut actuel : ${OUT:-0}" done echo "✅ L'émulateur Android est prêt !" - echo "Installation de l'APK de Debug..." + echo "⌛ Installation de l'APK de Debug..." adb install /src/_src/src/PostIt/PostIt.Android/bin/Debug/net10.0-android/fr.pschneider.postit-Signed.apk dotnet test /src/_src/src/PostIt/PostIt.Tests/PostIt.Tests.csproj -c Release - name: Test - echo "⌛ Lancement des tests ..." - run: cd /src/_src && dotnet test --no-build --verbosity normal - + run: | + echo "⌛ Lancement des tests..." + cd /src/_src && dotnet test --no-build --verbosity normal From 43dd526e4f2f9ce52a6b345961075424ac50088e Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 25 Aug 2026 23:07:19 +0100 Subject: [PATCH 20/73] fixes the step title --- .forgejo/workflows/buildAndTest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index a3f63cef..8180eead 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -47,7 +47,7 @@ jobs: run: cd /src/_src && dotnet restore - name: Build run: cd /src/_src && dotnet build --no-restore - - name: Démarrer l'émulateur QEMU Headless et exécuter les tests + - name: Démarrer l'émulateur QEMU Headless run: | echo "Démarrage de l'émulateur en tâche de fond..." # Remplacer 'pixel_5_api_30' par le nom exact de votre AVD créé sur l'hôte From 14b0cdb6a4024d885675accdf162ce70f3e6383e Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 25 Aug 2026 23:14:50 +0100 Subject: [PATCH 21/73] undated --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index acb3c275..bec19e53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,8 @@ pour la production des paquets `.deb`. ### Changed -mostly nothing but refactorings +L'identifiant de l'application client Android a changé, il passe en minuscules : +`fr.pschneider.postit` ### Fixed From 863c549d51b3e228b5781e056f8077750af33fde Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 25 Aug 2026 23:17:17 +0100 Subject: [PATCH 22/73] reinstall when yet installed --- .forgejo/workflows/buildAndTest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 8180eead..1d97bb28 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -64,7 +64,7 @@ jobs: done echo "✅ L'émulateur Android est prêt !" echo "⌛ Installation de l'APK de Debug..." - adb install /src/_src/src/PostIt/PostIt.Android/bin/Debug/net10.0-android/fr.pschneider.postit-Signed.apk + adb install /src/_src/src/PostIt/PostIt.Android/bin/Debug/net10.0-android/fr.pschneider.postit-Signed.apk -r dotnet test /src/_src/src/PostIt/PostIt.Tests/PostIt.Tests.csproj -c Release - name: Test From a4ae0fde728d19cb43ec4d9fde90b04ecda24106 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 25 Aug 2026 23:39:12 +0100 Subject: [PATCH 23/73] should work, Xamarin.UITest installs the app --- .forgejo/workflows/buildAndTest.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 1d97bb28..fe80aba1 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -63,10 +63,6 @@ jobs: echo "Statut actuel : ${OUT:-0}" done echo "✅ L'émulateur Android est prêt !" - echo "⌛ Installation de l'APK de Debug..." - adb install /src/_src/src/PostIt/PostIt.Android/bin/Debug/net10.0-android/fr.pschneider.postit-Signed.apk -r - dotnet test /src/_src/src/PostIt/PostIt.Tests/PostIt.Tests.csproj -c Release - - name: Test run: | echo "⌛ Lancement des tests..." From 0bb293c6eed5718be6d177d76627eb8c70170a8d Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 00:20:17 +0100 Subject: [PATCH 24/73] postit_test_avd --- .forgejo/workflows/buildAndTest.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index fe80aba1..80c6c9e6 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -49,9 +49,10 @@ jobs: run: cd /src/_src && dotnet build --no-restore - name: Démarrer l'émulateur QEMU Headless run: | + set -e echo "Démarrage de l'émulateur en tâche de fond..." # Remplacer 'pixel_5_api_30' par le nom exact de votre AVD créé sur l'hôte - emulator -avd emulator-5554 -no-window -no-audio -no-boot-anim -gpu swiftshader & + emulator -avd postit_test_avd -no-window -no-audio -no-boot-anim -gpu swiftshader & EMU_PID=$! echo "Attente de la détection par ADB..." adb wait-for-device @@ -63,6 +64,7 @@ jobs: echo "Statut actuel : ${OUT:-0}" done echo "✅ L'émulateur Android est prêt !" + - name: Test run: | echo "⌛ Lancement des tests..." From 553bd415a9a4c84d0009bad7df9847553fe2a6f7 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 01:24:19 +0100 Subject: [PATCH 25/73] comment cleanup --- .forgejo/workflows/buildAndTest.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 80c6c9e6..99ec4c0c 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -51,7 +51,6 @@ jobs: run: | set -e echo "Démarrage de l'émulateur en tâche de fond..." - # Remplacer 'pixel_5_api_30' par le nom exact de votre AVD créé sur l'hôte emulator -avd postit_test_avd -no-window -no-audio -no-boot-anim -gpu swiftshader & EMU_PID=$! echo "Attente de la détection par ADB..." From 36d58b6870930a54c2e3954055428ea04cd8b36e Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 01:42:59 +0100 Subject: [PATCH 26/73] simpler is better --- .forgejo/workflows/buildAndTest.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 99ec4c0c..bb3065ab 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -42,16 +42,12 @@ jobs: git checkout FETCH_HEAD fi git submodule update --init --recursive - echo "Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - - name: Restore dependencies - run: cd /src/_src && dotnet restore - - name: Build - run: cd /src/_src && dotnet build --no-restore + echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - name: Démarrer l'émulateur QEMU Headless run: | set -e echo "Démarrage de l'émulateur en tâche de fond..." - emulator -avd postit_test_avd -no-window -no-audio -no-boot-anim -gpu swiftshader & + emulator -avd pixel_test -no-window -no-audio -no-boot-anim -gpu swiftshader & EMU_PID=$! echo "Attente de la détection par ADB..." adb wait-for-device @@ -63,8 +59,7 @@ jobs: echo "Statut actuel : ${OUT:-0}" done echo "✅ L'émulateur Android est prêt !" - - name: Test run: | echo "⌛ Lancement des tests..." - cd /src/_src && dotnet test --no-build --verbosity normal + cd /src/_src && dotnet test --verbosity normal From 9d5667c459084ae2852fcc31274cfb583d9b65f0 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 01:49:57 +0100 Subject: [PATCH 27/73] to be clear --- .forgejo/workflows/buildAndTest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index bb3065ab..952ac493 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -62,4 +62,4 @@ jobs: - name: Test run: | echo "⌛ Lancement des tests..." - cd /src/_src && dotnet test --verbosity normal + cd /src/_src && dotnet test --verbosity normal && echo "✅ Success !" From dab56e508f166a8bfea249c164251205709d0afc Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 02:24:03 +0100 Subject: [PATCH 28/73] hit the AVD --- .forgejo/workflows/buildAndTest.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 952ac493..62f2e9f3 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -46,6 +46,7 @@ jobs: - name: Démarrer l'émulateur QEMU Headless run: | set -e + export ANDROID_AVD_HOME=${ANDROID_HOME}/.android/avd echo "Démarrage de l'émulateur en tâche de fond..." emulator -avd pixel_test -no-window -no-audio -no-boot-anim -gpu swiftshader & EMU_PID=$! From 70ad5100be90180cffd858e77248c84ea1e9a7de Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 03:55:21 +0100 Subject: [PATCH 29/73] yatry --- .forgejo/workflows/buildAndTest.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 62f2e9f3..3c55894d 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -27,9 +27,6 @@ jobs: build: runs-on: docker - container: - # Options cruciales pour donner accès à KVM et autoriser l'émulation - options: --device /dev/kvm --privileged steps: - name: Clone yavsc @@ -47,9 +44,16 @@ jobs: run: | set -e export ANDROID_AVD_HOME=${ANDROID_HOME}/.android/avd - echo "Démarrage de l'émulateur en tâche de fond..." - emulator -avd pixel_test -no-window -no-audio -no-boot-anim -gpu swiftshader & + + adb start-server + echo "⌛ Démarrage de l'émulateur en tâche de fond..." + emulator -avd pixel_test \ + -no-window \ + -no-audio \ + -no-boot-anim \ + -gpu off & EMU_PID=$! + echo "Attente de la détection par ADB..." adb wait-for-device echo "Attente de la fin du boot d'Android..." From a9c18d670812128b0ebaa6c26f3fdc666744f88f Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 04:52:57 +0100 Subject: [PATCH 30/73] emulator --- .forgejo/workflows/buildAndTest.yml | 35 +++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 3c55894d..7b810119 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -25,9 +25,10 @@ on: jobs: build: - runs-on: docker - + container: + image: pazof/yavsc-build-env:debian12-dotnet10-android36-v5 + options: --device /dev/kvm --privileged steps: - name: Clone yavsc run: | @@ -40,30 +41,50 @@ jobs: fi git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" + - name: Démarrer l'émulateur QEMU Headless run: | - set -e + # 1. Variables d'environnement pour stabiliser le noyau Android 36 + export RE_EMULATOR_DISABLE_CPUID_CHECK=1 + export ANDROID_EMULATOR_DISABLE_VULKAN=1 + export ANDROID_EMULATOR_FORCE_GLES_2=1 + export ANDROID_HOME=/opt/android-sdk export ANDROID_AVD_HOME=${ANDROID_HOME}/.android/avd + # 2. Initialisation obligatoire du serveur ADB adb start-server + echo "⌛ Démarrage de l'émulateur en tâche de fond..." + + # 3. Lancement corrigé : exclusion de -gpu off (qui brise SwiftShader) et forçage d'un profil CPU standard emulator -avd pixel_test \ -no-window \ -no-audio \ -no-boot-anim \ - -gpu off & - EMU_PID=$! + -gpu swiftshader \ + -no-metrics \ + -qemu -cpu max,fma=off,avx2=off,bmi1=off,bmi2=off & echo "Attente de la détection par ADB..." adb wait-for-device + echo "Attente de la fin du boot d'Android..." OUT="" - while [[ "$OUT" != "1" ]]; do - sleep 5 + COUNTER=0 + # Sécurité : ajout d'un timeout (max 30 essais) pour éviter que la CI ne tourne à l'infini si le boot gèle + while [[ "$OUT" != "1" && $COUNTER -lt 30 ]]; do + sleep 10 OUT=$(adb shell getprop sys.boot_completed | tr -d '\r') echo "Statut actuel : ${OUT:-0}" + let COUNTER=COUNTER+1 done + + if [ "$OUT" != "1" ]; then + echo "❌ Échec du boot d'Android après délai imparti." + exit 1 + fi echo "✅ L'émulateur Android est prêt !" + - name: Test run: | echo "⌛ Lancement des tests..." From 851920c79e0ba4f49deeb44a67c8d7eda4221134 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 05:09:02 +0100 Subject: [PATCH 31/73] specify the docker image --- .forgejo/workflows/buildAndTest.yml | 6 ++++++ .forgejo/workflows/release.yml | 2 ++ 2 files changed, 8 insertions(+) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 7b810119..7b587fb0 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -87,5 +87,11 @@ jobs: - name: Test run: | + echo "⌛ Installation de l'APK de Debug..." + # Ajustez le chemin vers l'APK généré par votre build de debug + cd /src/_src + APK=src/PostIt/PostIt.Android/bin/Debug/net10.0-android/android-arm64/fr.pschneider.postit-Signed.apk + adb install ${APK} + echo "⌛ Lancement des tests..." cd /src/_src && dotnet test --verbosity normal && echo "✅ Success !" diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index cf6594ec..a4f86b37 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -51,6 +51,8 @@ jobs: # via l'API REST Forgejo (pas d'actions tierces Node). release: runs-on: docker + container: + image: pazof/yavsc-build-env:debian12-dotnet10-android36-v5 steps: - name: Clone du repo au tag demandé env: From 1a79ee93ebedd72d9abc34d6c9e9a13f7af40a73 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 05:15:13 +0100 Subject: [PATCH 32/73] avd name changed --- .forgejo/workflows/buildAndTest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 7b587fb0..95eb2958 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -57,7 +57,7 @@ jobs: echo "⌛ Démarrage de l'émulateur en tâche de fond..." # 3. Lancement corrigé : exclusion de -gpu off (qui brise SwiftShader) et forçage d'un profil CPU standard - emulator -avd pixel_test \ + emulator -avd postit_test_avd \ -no-window \ -no-audio \ -no-boot-anim \ From 801839465ce90bf4d6bc841bd3cf28ed6cc3231d Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 05:25:18 +0100 Subject: [PATCH 33/73] =?UTF-8?q?donne=20l'acc=C3=A8s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .forgejo/workflows/buildAndTest.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 95eb2958..e9c3fe89 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -41,7 +41,10 @@ jobs: fi git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - + - name: Préparer les permissions KVM dans le conteneur + run: | + # Donne l'accès en écriture à tout le monde sur le périphérique KVM mappé + sudo chmod 666 /dev/kvm || true - name: Démarrer l'émulateur QEMU Headless run: | # 1. Variables d'environnement pour stabiliser le noyau Android 36 From bc6861dd26d1cbca376a0d26b15f2e1a50792288 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 05:38:07 +0100 Subject: [PATCH 34/73] no kvm --- .forgejo/workflows/buildAndTest.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index e9c3fe89..60a40d7a 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -59,14 +59,10 @@ jobs: echo "⌛ Démarrage de l'émulateur en tâche de fond..." - # 3. Lancement corrigé : exclusion de -gpu off (qui brise SwiftShader) et forçage d'un profil CPU standard emulator -avd postit_test_avd \ -no-window \ -no-audio \ - -no-boot-anim \ - -gpu swiftshader \ - -no-metrics \ - -qemu -cpu max,fma=off,avx2=off,bmi1=off,bmi2=off & + -no-boot-anim & echo "Attente de la détection par ADB..." adb wait-for-device From af1ca7b1bb60f761c4f4220c3853bcd8b764a16f Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 05:44:46 +0100 Subject: [PATCH 35/73] for reading --- .forgejo/workflows/buildAndTest.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 60a40d7a..09a53f04 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -44,7 +44,8 @@ jobs: - name: Préparer les permissions KVM dans le conteneur run: | # Donne l'accès en écriture à tout le monde sur le périphérique KVM mappé - sudo chmod 666 /dev/kvm || true + chmod 666 /dev/kvm + - name: Démarrer l'émulateur QEMU Headless run: | # 1. Variables d'environnement pour stabiliser le noyau Android 36 @@ -57,17 +58,20 @@ jobs: # 2. Initialisation obligatoire du serveur ADB adb start-server - echo "⌛ Démarrage de l'émulateur en tâche de fond..." + echo "🚀 Démarrage de l'émulateur en tâche de fond..." emulator -avd postit_test_avd \ -no-window \ -no-audio \ - -no-boot-anim & + -no-boot-anim \ + -gpu swiftshader \ + -no-metrics \ + -qemu -cpu max,fma=off,avx2=off,bmi1=off,bmi2=off & - echo "Attente de la détection par ADB..." + echo "⌛ Attente de la détection par ADB..." adb wait-for-device - echo "Attente de la fin du boot d'Android..." + echo "⌛ Attente de la fin du boot d'Android..." OUT="" COUNTER=0 # Sécurité : ajout d'un timeout (max 30 essais) pour éviter que la CI ne tourne à l'infini si le boot gèle @@ -86,11 +90,11 @@ jobs: - name: Test run: | - echo "⌛ Installation de l'APK de Debug..." + echo "🚀 Installation de l'APK de Debug..." # Ajustez le chemin vers l'APK généré par votre build de debug cd /src/_src APK=src/PostIt/PostIt.Android/bin/Debug/net10.0-android/android-arm64/fr.pschneider.postit-Signed.apk adb install ${APK} - echo "⌛ Lancement des tests..." + echo "🚀 Lancement des tests..." cd /src/_src && dotnet test --verbosity normal && echo "✅ Success !" From 4f9acb17ff16bcfa648a6f51a471a622185b6258 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 06:07:50 +0100 Subject: [PATCH 36/73] pour test --- .forgejo/workflows/buildAndTest.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 09a53f04..ab6c6975 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -28,7 +28,6 @@ jobs: runs-on: docker container: image: pazof/yavsc-build-env:debian12-dotnet10-android36-v5 - options: --device /dev/kvm --privileged steps: - name: Clone yavsc run: | From 41a1febb248072448ed091b6f626f540b7f090d0 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 06:09:16 +0100 Subject: [PATCH 37/73] pour test --- .forgejo/workflows/buildAndTest.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index ab6c6975..a5577a69 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -42,8 +42,7 @@ jobs: echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - name: Préparer les permissions KVM dans le conteneur run: | - # Donne l'accès en écriture à tout le monde sur le périphérique KVM mappé - chmod 666 /dev/kvm + ls -l /dev/kvm - name: Démarrer l'émulateur QEMU Headless run: | From 7d1e5763ff520b6e844a219def3687355d7ba963 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 06:19:42 +0100 Subject: [PATCH 38/73] cleanup --- .forgejo/workflows/buildAndTest.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index a5577a69..b49ab75b 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -40,9 +40,6 @@ jobs: fi git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - - name: Préparer les permissions KVM dans le conteneur - run: | - ls -l /dev/kvm - name: Démarrer l'émulateur QEMU Headless run: | From 955725d7394a99bcb66a2117da68ed43018dcc5a Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 06:23:22 +0100 Subject: [PATCH 39/73] =?UTF-8?q?Diagnostic=20syst=C3=A8me=20absolu=20du?= =?UTF-8?q?=20Runner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .forgejo/workflows/buildAndTest.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index b49ab75b..3a9710bb 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -40,7 +40,16 @@ jobs: fi git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - + - name: Diagnostic système absolu du Runner + run: | + echo "=== Utilisateur actuel ===" + id + echo "=== Liste des périphériques visibles ===" + ls -la /dev/kvm 2>&1 || echo "❌ /dev/kvm INTROUVABLE" + echo "=== Groupes disponibles ===" + getent group || true + echo "=== Variables d'environnement du conteneur ===" + env - name: Démarrer l'émulateur QEMU Headless run: | # 1. Variables d'environnement pour stabiliser le noyau Android 36 From e337e25aa45a0abd1c8a64930a86114ec6fd1e00 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 06:27:04 +0100 Subject: [PATCH 40/73] Forcer l'appropriation et les droits KVM --- .forgejo/workflows/buildAndTest.yml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 3a9710bb..6f656f93 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -40,16 +40,12 @@ jobs: fi git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - - name: Diagnostic système absolu du Runner + - name: Forcer l'appropriation et les droits KVM pour Podman run: | - echo "=== Utilisateur actuel ===" - id - echo "=== Liste des périphériques visibles ===" - ls -la /dev/kvm 2>&1 || echo "❌ /dev/kvm INTROUVABLE" - echo "=== Groupes disponibles ===" - getent group || true - echo "=== Variables d'environnement du conteneur ===" - env + # 1. Supprime les restrictions d'ACL héritées de Podman Rootless + setfacl -b /dev/kvm || true + # 2. Force les droits en lecture/écriture totale pour tout le monde dans le conteneur + chmod 666 /dev/kvm - name: Démarrer l'émulateur QEMU Headless run: | # 1. Variables d'environnement pour stabiliser le noyau Android 36 From 8978225539963681c767e0d9ccf44ce7e5f2ab60 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 06:39:22 +0100 Subject: [PATCH 41/73] ne rien forcer --- .forgejo/workflows/buildAndTest.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 6f656f93..a66018f9 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -40,12 +40,6 @@ jobs: fi git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - - name: Forcer l'appropriation et les droits KVM pour Podman - run: | - # 1. Supprime les restrictions d'ACL héritées de Podman Rootless - setfacl -b /dev/kvm || true - # 2. Force les droits en lecture/écriture totale pour tout le monde dans le conteneur - chmod 666 /dev/kvm - name: Démarrer l'émulateur QEMU Headless run: | # 1. Variables d'environnement pour stabiliser le noyau Android 36 From 016d16fda4f978251052e965c519813e37013962 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 06:41:57 +0100 Subject: [PATCH 42/73] Injecter le groupe KVM --- .forgejo/workflows/buildAndTest.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index a66018f9..35c117b6 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -40,6 +40,13 @@ jobs: fi git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" + - name: Injecter le groupe KVM pour l'émulateur Android + run: | + # 1. Vérifie si le groupe kvm existe déjà à l'intérieur, sinon le crée avec le GID 232 détecté par Podman + if ! getent group kvm > /dev/null; then + echo "kvm:x:232:root" >> /etc/group + echo "✅ Groupe KVM injecté artificiellement" + fi - name: Démarrer l'émulateur QEMU Headless run: | # 1. Variables d'environnement pour stabiliser le noyau Android 36 From c338fb33ed7be55f4da1a8147535eb4b8c55a595 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 06:44:38 +0100 Subject: [PATCH 43/73] Injecte la ligne parfaite --- .forgejo/workflows/buildAndTest.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 35c117b6..6be303e4 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -42,11 +42,15 @@ jobs: echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - name: Injecter le groupe KVM pour l'émulateur Android run: | - # 1. Vérifie si le groupe kvm existe déjà à l'intérieur, sinon le crée avec le GID 232 détecté par Podman - if ! getent group kvm > /dev/null; then - echo "kvm:x:232:root" >> /etc/group - echo "✅ Groupe KVM injecté artificiellement" - fi + # 1. Nettoie toute ancienne ligne kvm pour éviter les doublons + sed -i '/^kvm:/d' /etc/group || true + + # 2. Injecte la ligne parfaite requise par la regex de l'émulateur Android + echo "kvm:x:232:root" >> /etc/group + + # 3. Vérification visuelle dans les logs de la CI + echo "=== Contenu validé pour l'émulateur ===" + grep kvm /etc/group - name: Démarrer l'émulateur QEMU Headless run: | # 1. Variables d'environnement pour stabiliser le noyau Android 36 From bbd869ab88a5a2a4e84b935b4efb9111a6625abd Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 06:48:18 +0100 Subject: [PATCH 44/73] export USER=root --- .forgejo/workflows/buildAndTest.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 6be303e4..e7b5b66b 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -42,17 +42,16 @@ jobs: echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - name: Injecter le groupe KVM pour l'émulateur Android run: | - # 1. Nettoie toute ancienne ligne kvm pour éviter les doublons + # 1. Nettoie l'ancien résidu sed -i '/^kvm:/d' /etc/group || true - # 2. Injecte la ligne parfaite requise par la regex de l'émulateur Android + # 2. Injecte la correspondance exacte requise echo "kvm:x:232:root" >> /etc/group - - # 3. Vérification visuelle dans les logs de la CI - echo "=== Contenu validé pour l'émulateur ===" - grep kvm /etc/group - name: Démarrer l'émulateur QEMU Headless run: | + export USER=root + export USERNAME=root + # 1. Variables d'environnement pour stabiliser le noyau Android 36 export RE_EMULATOR_DISABLE_CPUID_CHECK=1 export ANDROID_EMULATOR_DISABLE_VULKAN=1 From 955d925f33ce439b6522c339e399a00bb3b489d2 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 06:53:28 +0100 Subject: [PATCH 45/73] -no-accel-check --- .forgejo/workflows/buildAndTest.yml | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index e7b5b66b..59212de3 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -40,18 +40,8 @@ jobs: fi git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - - name: Injecter le groupe KVM pour l'émulateur Android - run: | - # 1. Nettoie l'ancien résidu - sed -i '/^kvm:/d' /etc/group || true - - # 2. Injecte la correspondance exacte requise - echo "kvm:x:232:root" >> /etc/group - name: Démarrer l'émulateur QEMU Headless run: | - export USER=root - export USERNAME=root - # 1. Variables d'environnement pour stabiliser le noyau Android 36 export RE_EMULATOR_DISABLE_CPUID_CHECK=1 export ANDROID_EMULATOR_DISABLE_VULKAN=1 @@ -64,14 +54,7 @@ jobs: echo "🚀 Démarrage de l'émulateur en tâche de fond..." - emulator -avd postit_test_avd \ - -no-window \ - -no-audio \ - -no-boot-anim \ - -gpu swiftshader \ - -no-metrics \ - -qemu -cpu max,fma=off,avx2=off,bmi1=off,bmi2=off & - + emulator -avd postit_test_avd -no-window -no-audio -no-accel-check & echo "⌛ Attente de la détection par ADB..." adb wait-for-device From 7ccb23ba2836676c802f6ef212ccc7c64d4ccdac Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 06:58:47 +0100 Subject: [PATCH 46/73] try the direct call --- .forgejo/workflows/buildAndTest.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 59212de3..b1644627 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -46,15 +46,14 @@ jobs: export RE_EMULATOR_DISABLE_CPUID_CHECK=1 export ANDROID_EMULATOR_DISABLE_VULKAN=1 export ANDROID_EMULATOR_FORCE_GLES_2=1 - export ANDROID_HOME=/opt/android-sdk - export ANDROID_AVD_HOME=${ANDROID_HOME}/.android/avd + # 1. Variables de stabilisation + export RE_EMULATOR_DISABLE_CPUID_CHECK=1 + export ANDROID_EMULATOR_DISABLE_VULKAN=1 - # 2. Initialisation obligatoire du serveur ADB - adb start-server + # 2. Appel direct du moteur sans passer par le script de vérification de Google + # Remplacez "postit_test_avd" par le nom exact de votre AVD + /opt/android-sdk/emulator/qemu/linux-x86_64/qemu-system-x86_64 -avd postit_test_avd -no-window -no-audio & - echo "🚀 Démarrage de l'émulateur en tâche de fond..." - - emulator -avd postit_test_avd -no-window -no-audio -no-accel-check & echo "⌛ Attente de la détection par ADB..." adb wait-for-device From 7e3b0a72ade1e35ce2f46201c722b70a7658a0d6 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 07:03:03 +0100 Subject: [PATCH 47/73] LD_LIBRARY_PATH --- .forgejo/workflows/buildAndTest.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index b1644627..b2c9263a 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -49,6 +49,7 @@ jobs: # 1. Variables de stabilisation export RE_EMULATOR_DISABLE_CPUID_CHECK=1 export ANDROID_EMULATOR_DISABLE_VULKAN=1 + export LD_LIBRARY_PATH=/opt/android-sdk/emulator/lib64:$LD_LIBRARY_PATH # 2. Appel direct du moteur sans passer par le script de vérification de Google # Remplacez "postit_test_avd" par le nom exact de votre AVD From c4f6913fdb1165ca4ff67cdeb81d2af01bd57f02 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 07:05:00 +0100 Subject: [PATCH 48/73] LD_LIBRARY_PATH 2 --- .forgejo/workflows/buildAndTest.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index b2c9263a..4fa26f61 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -49,7 +49,8 @@ jobs: # 1. Variables de stabilisation export RE_EMULATOR_DISABLE_CPUID_CHECK=1 export ANDROID_EMULATOR_DISABLE_VULKAN=1 - export LD_LIBRARY_PATH=/opt/android-sdk/emulator/lib64:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH=/opt/android-sdk/emulator/lib64:/opt/android-sdk/emulator/lib64/qt/lib:$LD_LIBRARY_PATH + # 2. Appel direct du moteur sans passer par le script de vérification de Google # Remplacez "postit_test_avd" par le nom exact de votre AVD From 8f9c55bf2d3f1424ab89826f0fba576f3598be38 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 07:09:10 +0100 Subject: [PATCH 49/73] apt-get update && apt-get install --- .forgejo/workflows/buildAndTest.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 4fa26f61..0bc21065 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -51,6 +51,7 @@ jobs: export ANDROID_EMULATOR_DISABLE_VULKAN=1 export LD_LIBRARY_PATH=/opt/android-sdk/emulator/lib64:/opt/android-sdk/emulator/lib64/qt/lib:$LD_LIBRARY_PATH + apt-get update && apt-get install -y libxi6 libxext6 libxrender1 libxtst6 # 2. Appel direct du moteur sans passer par le script de vérification de Google # Remplacez "postit_test_avd" par le nom exact de votre AVD From 800323915985c29c09f07b318b0ad4638b081d41 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 08:08:13 +0100 Subject: [PATCH 50/73] docker image version bump --- .forgejo/workflows/buildAndTest.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 0bc21065..5f5f62a5 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -27,7 +27,7 @@ jobs: build: runs-on: docker container: - image: pazof/yavsc-build-env:debian12-dotnet10-android36-v5 + image: pazof/yavsc-build-env:debian13-dotnet10-android36-v6 steps: - name: Clone yavsc run: | @@ -46,16 +46,10 @@ jobs: export RE_EMULATOR_DISABLE_CPUID_CHECK=1 export ANDROID_EMULATOR_DISABLE_VULKAN=1 export ANDROID_EMULATOR_FORCE_GLES_2=1 - # 1. Variables de stabilisation export RE_EMULATOR_DISABLE_CPUID_CHECK=1 export ANDROID_EMULATOR_DISABLE_VULKAN=1 - export LD_LIBRARY_PATH=/opt/android-sdk/emulator/lib64:/opt/android-sdk/emulator/lib64/qt/lib:$LD_LIBRARY_PATH - apt-get update && apt-get install -y libxi6 libxext6 libxrender1 libxtst6 - - # 2. Appel direct du moteur sans passer par le script de vérification de Google - # Remplacez "postit_test_avd" par le nom exact de votre AVD - /opt/android-sdk/emulator/qemu/linux-x86_64/qemu-system-x86_64 -avd postit_test_avd -no-window -no-audio & + emulator -avd postit_test_avd -no-window -no-audio & echo "⌛ Attente de la détection par ADB..." adb wait-for-device From f7956b045968b4f54d21a681dd993ed31e489a62 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 08:28:19 +0100 Subject: [PATCH 51/73] appel direct --- .forgejo/workflows/buildAndTest.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 5f5f62a5..629e516c 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -48,8 +48,9 @@ jobs: export ANDROID_EMULATOR_FORCE_GLES_2=1 export RE_EMULATOR_DISABLE_CPUID_CHECK=1 export ANDROID_EMULATOR_DISABLE_VULKAN=1 + export LD_LIBRARY_PATH=/opt/android-sdk/emulator/lib64:/opt/android-sdk/emulator/lib64/qt/lib:$LD_LIBRARY_PATH - emulator -avd postit_test_avd -no-window -no-audio & + /opt/android-sdk/emulator/qemu/linux-x86_64/qemu-system-x86_64 -avd postit_test_avd -no-window -no-audio & echo "⌛ Attente de la détection par ADB..." adb wait-for-device From 1ba114ee332d219b4f1ff9f6fa59dc5d4e94e7a7 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 08:44:44 +0100 Subject: [PATCH 52/73] gpu swiftshader --- .forgejo/workflows/buildAndTest.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 629e516c..b5169a1c 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -50,7 +50,13 @@ jobs: export ANDROID_EMULATOR_DISABLE_VULKAN=1 export LD_LIBRARY_PATH=/opt/android-sdk/emulator/lib64:/opt/android-sdk/emulator/lib64/qt/lib:$LD_LIBRARY_PATH - /opt/android-sdk/emulator/qemu/linux-x86_64/qemu-system-x86_64 -avd postit_test_avd -no-window -no-audio & + emulator -avd postit_test_avd \ + -no-window \ + -no-audio \ + -no-boot-anim \ + -gpu swiftshader \ + -no-metrics \ + -timezone Europe/Paris & echo "⌛ Attente de la détection par ADB..." adb wait-for-device From eb0cf11703d5d43b5342caf1f1c5155660863e77 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 08:50:35 +0100 Subject: [PATCH 53/73] -cpu host --- .forgejo/workflows/buildAndTest.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index b5169a1c..050ac917 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -56,7 +56,8 @@ jobs: -no-boot-anim \ -gpu swiftshader \ -no-metrics \ - -timezone Europe/Paris & + -cores 2 \ + -qemu -cpu host & echo "⌛ Attente de la détection par ADB..." adb wait-for-device From 696117ac5a53acd1c18cc6ba55b5656e615a2922 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 08:56:14 +0100 Subject: [PATCH 54/73] another try --- .forgejo/workflows/buildAndTest.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 050ac917..5dd369e0 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -44,12 +44,12 @@ jobs: run: | # 1. Variables d'environnement pour stabiliser le noyau Android 36 export RE_EMULATOR_DISABLE_CPUID_CHECK=1 - export ANDROID_EMULATOR_DISABLE_VULKAN=1 - export ANDROID_EMULATOR_FORCE_GLES_2=1 - export RE_EMULATOR_DISABLE_CPUID_CHECK=1 - export ANDROID_EMULATOR_DISABLE_VULKAN=1 - export LD_LIBRARY_PATH=/opt/android-sdk/emulator/lib64:/opt/android-sdk/emulator/lib64/qt/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH=/opt/android-sdk/emulator/lib64:/opt/android-sdk/emulator/lib64/qt/lib:$LD_LIBRARY_PATH + export QT_QPA_PLATFORM=offscreen + export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1 + + # 2. Démarrer l'émulateur QEMU Headless emulator -avd postit_test_avd \ -no-window \ -no-audio \ From 1e3239498c51a1cbe20f71fd05167f57aacdfccc Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 08:58:46 +0100 Subject: [PATCH 55/73] -gpu software --- .forgejo/workflows/buildAndTest.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 5dd369e0..62c21784 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -54,10 +54,11 @@ jobs: -no-window \ -no-audio \ -no-boot-anim \ - -gpu swiftshader \ + -gpu software \ -no-metrics \ -cores 2 \ - -qemu -cpu host & + -memory 2048 \ + -qemu -cpu host,vme=off & echo "⌛ Attente de la détection par ADB..." adb wait-for-device From f285a168bd1c3a72bee5ae38cca910b281e52140 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 09:18:38 +0100 Subject: [PATCH 56/73] settings --- .forgejo/workflows/buildAndTest.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 62c21784..092dea0e 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -40,6 +40,8 @@ jobs: fi git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" + - name: check kvm + run: /sbin/kvm-ok - name: Démarrer l'émulateur QEMU Headless run: | # 1. Variables d'environnement pour stabiliser le noyau Android 36 @@ -48,6 +50,19 @@ jobs: export LD_LIBRARY_PATH=/opt/android-sdk/emulator/lib64:/opt/android-sdk/emulator/lib64/qt/lib:$LD_LIBRARY_PATH export QT_QPA_PLATFORM=offscreen export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1 + export ANDROID_SDK_ROOT=/opt/android-sdk + + echo "hw.ramSize = 3072" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini + echo "hw.ramSize = 2048" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini + echo "hw.heapSize = 256" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini + echo "hw.gpu.enabled = yes" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini + echo "hw.gpu.mode = host" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini + echo "Vulkan = off" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini + echo "enableHostVulkan = no" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini + +GLDirectMem = off +" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini + # 2. Démarrer l'émulateur QEMU Headless emulator -avd postit_test_avd \ From e266c1de6eab4f250c01f15ea822e10516a7b445 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 09:20:36 +0100 Subject: [PATCH 57/73] syntax --- .forgejo/workflows/buildAndTest.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 092dea0e..3556c655 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -59,9 +59,7 @@ jobs: echo "hw.gpu.mode = host" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini echo "Vulkan = off" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini echo "enableHostVulkan = no" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini - -GLDirectMem = off -" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini + echo "GLDirectMem = off" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini # 2. Démarrer l'émulateur QEMU Headless From d6b45024dc7a8353ab664ca9998c90f7b0fb73d8 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 09:21:44 +0100 Subject: [PATCH 58/73] kvm-ok is to install (or not?) --- .forgejo/workflows/buildAndTest.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 3556c655..c20763d6 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -40,8 +40,7 @@ jobs: fi git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - - name: check kvm - run: /sbin/kvm-ok + - name: Démarrer l'émulateur QEMU Headless run: | # 1. Variables d'environnement pour stabiliser le noyau Android 36 From 39400baadb68e2ac3b96e995af4cb77cd5eb5f29 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 09:25:23 +0100 Subject: [PATCH 59/73] giving up --- .forgejo/workflows/buildAndTest.yml | 51 ----------------------------- 1 file changed, 51 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index c20763d6..11eb196e 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -41,57 +41,6 @@ jobs: git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - - name: Démarrer l'émulateur QEMU Headless - run: | - # 1. Variables d'environnement pour stabiliser le noyau Android 36 - export RE_EMULATOR_DISABLE_CPUID_CHECK=1 - - export LD_LIBRARY_PATH=/opt/android-sdk/emulator/lib64:/opt/android-sdk/emulator/lib64/qt/lib:$LD_LIBRARY_PATH - export QT_QPA_PLATFORM=offscreen - export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1 - export ANDROID_SDK_ROOT=/opt/android-sdk - - echo "hw.ramSize = 3072" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini - echo "hw.ramSize = 2048" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini - echo "hw.heapSize = 256" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini - echo "hw.gpu.enabled = yes" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini - echo "hw.gpu.mode = host" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini - echo "Vulkan = off" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini - echo "enableHostVulkan = no" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini - echo "GLDirectMem = off" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini - - - # 2. Démarrer l'émulateur QEMU Headless - emulator -avd postit_test_avd \ - -no-window \ - -no-audio \ - -no-boot-anim \ - -gpu software \ - -no-metrics \ - -cores 2 \ - -memory 2048 \ - -qemu -cpu host,vme=off & - - echo "⌛ Attente de la détection par ADB..." - adb wait-for-device - - echo "⌛ Attente de la fin du boot d'Android..." - OUT="" - COUNTER=0 - # Sécurité : ajout d'un timeout (max 30 essais) pour éviter que la CI ne tourne à l'infini si le boot gèle - while [[ "$OUT" != "1" && $COUNTER -lt 30 ]]; do - sleep 10 - OUT=$(adb shell getprop sys.boot_completed | tr -d '\r') - echo "Statut actuel : ${OUT:-0}" - let COUNTER=COUNTER+1 - done - - if [ "$OUT" != "1" ]; then - echo "❌ Échec du boot d'Android après délai imparti." - exit 1 - fi - echo "✅ L'émulateur Android est prêt !" - - name: Test run: | echo "🚀 Installation de l'APK de Debug..." From b0e70eb1989d2279a627cdf1c5f83ccb264d1bd0 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 17:06:14 +0100 Subject: [PATCH 60/73] give a try to the v7 --- .forgejo/workflows/buildAndTest.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 11eb196e..c5797c6c 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -27,7 +27,7 @@ jobs: build: runs-on: docker container: - image: pazof/yavsc-build-env:debian13-dotnet10-android36-v6 + image: pazof/yavsc-build-env:debian13-dotnet10-android36-v7 steps: - name: Clone yavsc run: | @@ -40,6 +40,20 @@ jobs: fi git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" + - name: setup avd qemu + run: | + export QT_QPA_PLATFORM=offscreen + export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1 + export ANDROID_SDK_ROOT=/opt/android-sdk + + echo "hw.ramSize = 3072" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini + echo "hw.ramSize = 2048" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini + echo "hw.heapSize = 256" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini + echo "hw.gpu.enabled = yes" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini + echo "hw.gpu.mode = host" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini + echo "Vulkan = off" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini + echo "enableHostVulkan = no" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini + echo "GLDirectMem = off" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini - name: Test run: | From 99c500d177cfb4e21528f8f992bc9b085a3a8e8a Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 17:13:20 +0100 Subject: [PATCH 61/73] start qemu --- .forgejo/workflows/buildAndTest.yml | 33 +++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index c5797c6c..ccdd0a6c 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -55,6 +55,39 @@ jobs: echo "enableHostVulkan = no" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini echo "GLDirectMem = off" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini + - name: Start qemu avd + run: | + # 2. Démarrer l'émulateur QEMU Headless + emulator -avd postit_test_avd \ + -no-window \ + -no-audio \ + -no-boot-anim \ + -no-metrics \ + -cores 2 \ + -memory 2048 & + + echo "⌛ Attente de la détection par ADB..." + adb wait-for-device + + echo "⌛ Attente de la fin du boot d'Android..." + OUT="" + + COUNTER=0 + # Sécurité : ajout d'un timeout (max 30 essais) pour éviter + { que la CI ne tourne à l'infini si le boot gèle + while [[ "$OUT" != "1" && $COUNTER -lt 30 ]]; do + sleep 10 + OUT=$(adb shell getprop sys.boot_completed | tr -d '\r') + echo "Statut actuel : ${OUT:-0}" + let COUNTER=COUNTER+1 + done + + if [ "$OUT" != "1" ]; then + echo "❌ Échec du boot d'Android après délai imparti." + exit 1 + fi + echo "✅ L'émulateur Android est prêt !" + - name: Test run: | echo "🚀 Installation de l'APK de Debug..." From d63f065e035a8d6c8270f0cbcfa755bd78d9a306 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 17:15:11 +0100 Subject: [PATCH 62/73] try host cpu --- .forgejo/workflows/buildAndTest.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index ccdd0a6c..815bab07 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -64,7 +64,8 @@ jobs: -no-boot-anim \ -no-metrics \ -cores 2 \ - -memory 2048 & + -memory 2048 \ + -qemu -cpu host,vme=off & echo "⌛ Attente de la détection par ADB..." adb wait-for-device From 98cab22e60e32b8e69297ce14494d2907d1209bd Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 17:16:47 +0100 Subject: [PATCH 63/73] RE_EMULATOR_DISABLE_CPUID_CHECK --- .forgejo/workflows/buildAndTest.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 815bab07..3de2adf2 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -45,6 +45,7 @@ jobs: export QT_QPA_PLATFORM=offscreen export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1 export ANDROID_SDK_ROOT=/opt/android-sdk + export RE_EMULATOR_DISABLE_CPUID_CHECK=1 echo "hw.ramSize = 3072" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini echo "hw.ramSize = 2048" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini From 29d842a8f94d3fdb8798f843d7aa2f4c2a538f43 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 17:18:31 +0100 Subject: [PATCH 64/73] -cores 1 --- .forgejo/workflows/buildAndTest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 3de2adf2..b6694c2c 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -64,7 +64,7 @@ jobs: -no-audio \ -no-boot-anim \ -no-metrics \ - -cores 2 \ + -cores 1 \ -memory 2048 \ -qemu -cpu host,vme=off & From 366cd0eed93f2609ae0b0f79362f8edb9619a182 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 17:22:03 +0100 Subject: [PATCH 65/73] try with vulkan enabled --- .forgejo/workflows/buildAndTest.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index b6694c2c..c7347135 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -52,9 +52,6 @@ jobs: echo "hw.heapSize = 256" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini echo "hw.gpu.enabled = yes" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini echo "hw.gpu.mode = host" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini - echo "Vulkan = off" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini - echo "enableHostVulkan = no" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini - echo "GLDirectMem = off" >> ${ANDROID_SDK_ROOT}/.android/avd/advancedFeatures.ini - name: Start qemu avd run: | From bfcb7cd2efa396dd61729faacbd94611487e5d3d Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 19:23:27 +0100 Subject: [PATCH 66/73] disable the Xamarin.UITest --- .forgejo/workflows/buildAndTest.yml | 46 ------------------- .../PostIt.Tests/AndroidAppLaunchTests.cs | 3 +- 2 files changed, 2 insertions(+), 47 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index c7347135..7e0bc2b0 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -40,52 +40,6 @@ jobs: fi git submodule update --init --recursive echo "✅ Checked out at $(git rev-parse HEAD) on $(git branch --show-current 2>/dev/null || echo detached HEAD)" - - name: setup avd qemu - run: | - export QT_QPA_PLATFORM=offscreen - export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1 - export ANDROID_SDK_ROOT=/opt/android-sdk - export RE_EMULATOR_DISABLE_CPUID_CHECK=1 - - echo "hw.ramSize = 3072" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini - echo "hw.ramSize = 2048" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini - echo "hw.heapSize = 256" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini - echo "hw.gpu.enabled = yes" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini - echo "hw.gpu.mode = host" >> ${ANDROID_SDK_ROOT}/.android/avd/postit_test_avd.ini - - - name: Start qemu avd - run: | - # 2. Démarrer l'émulateur QEMU Headless - emulator -avd postit_test_avd \ - -no-window \ - -no-audio \ - -no-boot-anim \ - -no-metrics \ - -cores 1 \ - -memory 2048 \ - -qemu -cpu host,vme=off & - - echo "⌛ Attente de la détection par ADB..." - adb wait-for-device - - echo "⌛ Attente de la fin du boot d'Android..." - OUT="" - - COUNTER=0 - # Sécurité : ajout d'un timeout (max 30 essais) pour éviter - { que la CI ne tourne à l'infini si le boot gèle - while [[ "$OUT" != "1" && $COUNTER -lt 30 ]]; do - sleep 10 - OUT=$(adb shell getprop sys.boot_completed | tr -d '\r') - echo "Statut actuel : ${OUT:-0}" - let COUNTER=COUNTER+1 - done - - if [ "$OUT" != "1" ]; then - echo "❌ Échec du boot d'Android après délai imparti." - exit 1 - fi - echo "✅ L'émulateur Android est prêt !" - name: Test run: | diff --git a/src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs b/src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs index 8a256afc..d4980d26 100644 --- a/src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs +++ b/src/PostIt/PostIt.Tests/AndroidAppLaunchTests.cs @@ -23,7 +23,8 @@ public class AndroidAppLaunchTests _output = output; } - [Fact] + // https://twosixtech.com/blog/integrating-docker-and-adb/ + // FIXME ala hosted shared resource adb server - [Fact] public void PostIt_starts_and_draws_a_first_frame_on_the_emulator() { if (!IsPackageInstalledOnAnyDevice()) From 45299d14c1f8cf1ec7073a4d94525ca75ee3398a Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 19:27:43 +0100 Subject: [PATCH 67/73] no apk to install --- .forgejo/workflows/buildAndTest.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index 7e0bc2b0..c29b844a 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -43,11 +43,5 @@ jobs: - name: Test run: | - echo "🚀 Installation de l'APK de Debug..." - # Ajustez le chemin vers l'APK généré par votre build de debug - cd /src/_src - APK=src/PostIt/PostIt.Android/bin/Debug/net10.0-android/android-arm64/fr.pschneider.postit-Signed.apk - adb install ${APK} - echo "🚀 Lancement des tests..." cd /src/_src && dotnet test --verbosity normal && echo "✅ Success !" From 5d81ab3094514d116603e4af241cbe64660d0dd2 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 19:43:47 +0100 Subject: [PATCH 68/73] Release 1.0.8-rc3 --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bec19e53..6adf462a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,8 +20,8 @@ pour la production des paquets `.deb`. ### Added -* a code cleanup -* a first Xamarin.UITest is successful +* a code cleanup, +* a first Xamarin.UITest is successful, but disabled, because breaking the actual CI process, * Android app starts, the login process succeeds ### Changed From 400db949531ede4014a5c4922e1903b090394299 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 19:49:42 +0100 Subject: [PATCH 69/73] hit the runner --- .forgejo/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index a4f86b37..00e91a41 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -52,7 +52,7 @@ jobs: release: runs-on: docker container: - image: pazof/yavsc-build-env:debian12-dotnet10-android36-v5 + image: pazof/yavsc-build-env:debian12-dotnet10-android36-v7 steps: - name: Clone du repo au tag demandé env: From 912dd88a028f0064afce0d8d36dedc2394f07383 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 19:52:41 +0100 Subject: [PATCH 70/73] gives this release a title --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6adf462a..2c1cefde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ Cette convention est partagée avec le dépôt [`postit-debian`](https://forgejo.pschneider.fr/notazof/postit-debian) pour la production des paquets `.deb`. -## [1.0.8-rc3] - unstable +## [1.0.8-rc3] Client Alpha Android - unstable ### Added From 09c8d7971425fc8fb838c174de864955a044a57e Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 20:04:39 +0100 Subject: [PATCH 71/73] debian13! --- .forgejo/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index 00e91a41..d6fc2e61 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -52,7 +52,7 @@ jobs: release: runs-on: docker container: - image: pazof/yavsc-build-env:debian12-dotnet10-android36-v7 + image: pazof/yavsc-build-env:debian13-dotnet10-android36-v7 steps: - name: Clone du repo au tag demandé env: From ad2285b8c541b2e8a3bb988e80b2c1eef356ac5e Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 20:19:51 +0100 Subject: [PATCH 72/73] was breakingthe format --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c1cefde..6adf462a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ Cette convention est partagée avec le dépôt [`postit-debian`](https://forgejo.pschneider.fr/notazof/postit-debian) pour la production des paquets `.deb`. -## [1.0.8-rc3] Client Alpha Android - unstable +## [1.0.8-rc3] - unstable ### Added From 671afebc12ceea66fc0c9c7cbbb75a5387c75fe0 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Wed, 26 Aug 2026 22:26:14 +0100 Subject: [PATCH 73/73] Build image version bump --- .forgejo/workflows/buildAndTest.yml | 2 +- .forgejo/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/buildAndTest.yml b/.forgejo/workflows/buildAndTest.yml index c29b844a..86694c89 100644 --- a/.forgejo/workflows/buildAndTest.yml +++ b/.forgejo/workflows/buildAndTest.yml @@ -27,7 +27,7 @@ jobs: build: runs-on: docker container: - image: pazof/yavsc-build-env:debian13-dotnet10-android36-v7 + image: pazof/yavsc-build-env:debian13-dotnet10-android36-jdk21-v1 steps: - name: Clone yavsc run: | diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index d6fc2e61..930c97b9 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -52,7 +52,7 @@ jobs: release: runs-on: docker container: - image: pazof/yavsc-build-env:debian13-dotnet10-android36-v7 + image: pazof/yavsc-build-env:debian13-dotnet10-android36-jdk21-v1 steps: - name: Clone du repo au tag demandé env: