Commit graph

3 commits

Author SHA1 Message Date
12a71ada6a
doc: align navigation docs with VM-first pattern
The two recent commits (3fbbafc4, 0065de70) replaced the
OpenSettingsRequested event + CurrentViewModel assignment with
App.PushPageAsync(vm): the VM resolves the target ViewModel
through DI, App resolves the Control through the ViewLocator,
guards against double-push, and pushes via NavRoot. The docs
were still describing the pre-refactor world.

Update three places:

- CONTRIBUTING.md — the "Navigation (PostIt)" rule now
  describes App.PushPageAsync as the single channel and shows
  the canonical OpenSettings command as the example.
- doc/architecture/postit.md — the Navigation section
  distinguishes VM-first navigation (App.PushPageAsync) from
  lifecycle signals (LoginSucceeded, LogoutCompleted) and
  drops the obsolete OpenSettingsRequested row.
- src/PostIt/PostIt/App.axaml.cs — refresh the SettingsPage
  singleton justification: point (c) now describes the
  anti-empilement guard inside PushPageAsync, not the
  OpenSettingsRequested handler that no longer exists.

No production behaviour change — doc only (and the inline
comment that referenced a removed event).
2026-08-19 17:17:22 +01:00
1733dababb postIt: SettingsPage is a singleton, navigation is idempotent
Two related changes that close the loop on the SettingsPage
push semantics.

1. The SettingsPage used to be registered as Transient. Each
   click on the Paramètres button resolved a fresh instance,
   re-bound it to the Settings singleton, and pushed it onto
   the navigation stack. Repeated clicks accumulated stacked
   instances, each fully bound, and the user had to tap Back
   N times to leave. The fix is to register the page as a
   Singleton in the DI container. There is now one and only
   one SettingsPage ContentPage for the lifetime of the app:
     - its DataContext is wired once, at composition time
       (just after the ViewLocator is added to DataTemplates),
       not on every push;
     - the OpenSettingsRequested handler is a pure navigation
       concern, with no DI resolution and no rebinding;
     - the in-memory Settings state is preserved across visits
       (any in-flight edit stays in the same instance).

2. The OpenSettingsRequested handler is guarded so that if the
   SettingsPage is already at the top of NavigationStack, the
   push is a no-op. NavigationPage.PushAsync does not
   deduplicate; without the guard, calling it twice with the
   same instance pushes it a second time, and the user has to
   tap Back twice to leave. The guard is a reference comparison
   on NavigationStack[Count - 1] against the singleton
   instance, which is correct precisely because the page is
   a singleton.

doc/architecture/postit.md is updated to match: the DI table
reflects the new lifetime, and the 'Garde anti-empilement'
section is rewritten from 'to be implemented' to the actual
implementation, including the rationale for reference
comparison and the cross-dependency between the singleton
lifetime and the guard.

The Settings-singleton invariant (in the same doc) is
unchanged: Settings is still a singleton, and adding a
transient override would still be the bug it always was.
The new SettingsPage singleton sits alongside it cleanly.

Build: 0 errors. Tests: 3/3 SettingsLoadTests green.
2026-07-09 22:00:00 +01:00
120bae6f5c doc(arch): PostIt topology + up-to-date project list
Two long-standing gaps in the architecture documentation are
filled in this commit:

1. doc/architecture/postit.md is new. It covers everything the
   existing postit-oidc.md does not: the one-codebase /
   three-frontends topology (PostIt lib + PostIt.Desktop +
   PostIt.Android + PostIt.Browser), the custom ViewLocator
   that resolves ViewModel -> View through the DI provider
   (and why we don't use the Avalonia.Mvvm default), the
   composition root in App.OnFrameworkInitializationCompleted
   with the full DI registration table, the navigation flow
   driven by SessionStatusViewModel events, the ViewModel
   lifetime conventions (singleton vs transient), the
   [RelayCommand] XAML binding conventions (referenced to
   AGENTS.md for the canonical version), and the per-page
   DataContext / role table. The Settings-singleton invariant
   is called out as a guard rail, and the SettingsPage
   anti-empilement invariant is documented as the TODO the
   code still owes us.

2. doc/architecture/decoupage-organisation.md is brought up to
   date. Its project table listed 7 .csproj; the repo has 14
   (the four PostIt projects, the tests satellites, the cli
   tool). The table is extended, the ASCII diagram picks up
   the PostIt block, and an Outils et tests section lists
   the test / CLI satellites that were missing.

doc/README.md is updated to index the new postit.md. No code
changes in this commit, no behaviour change.
2026-07-09 21:54:06 +01:00