Phase 2 app lifecycle skeleton#2
Merged
Merged
Conversation
Explicit Program.cs Main: Velopack hook → ComWrappersSupport.InitializeComWrappers →
single-instance check via Windows App SDK AppInstance.FindOrRegisterForKey
("snipdeck") with activation redirect to the primary → Application.Start with
a DispatcherQueueSynchronizationContext. Disables the XAML-generated Main so
this order is load-bearing.
Bootstrap.cs builds the DI container
(Microsoft.Extensions.DependencyInjection 10.0.8). Settings are loaded
synchronously up front so the snip-store and backup paths can be resolved
(config value or path-provider default) before the rest of the graph is built.
New abstractions in Core: IPathProvider and IDispatcher.
New App-side services:
- WindowsPathProvider: paths rooted at %LOCALAPPDATA%\Snipdeck.
- WinUiDispatcher: lazy-captures the UI thread's DispatcherQueue on first
use; App constructor warms it up so the secondary-instance activation
handler can marshal back to the UI thread safely.
MainWindow:
- Mica backdrop (already on the scaffolded XAML).
- ExtendsContentIntoTitleBar + custom draggable title bar showing the app
name.
- Theme applied from AppConfig (Light / Dark / System).
App.xaml.cs:
- Owns the static IServiceProvider.
- Runs ExamplesSeed.Build() into the snip store on first run (empty store).
- Subscribes to AppInstance.Activated; a redirect from a secondary instance
foregrounds the existing main window.
Core tests still pass (63/63).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EnableDefaultXamlGeneratedMain=false alone doesn't propagate to the WinUI XAML compiler in WindowsAppSDK 2.1.0 — it still emits the Program class with its own Main, colliding with Program.cs. The compiler wraps that Program in #if !DISABLE_XAML_GENERATED_MAIN, so define that constant explicitly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…itions Program.cs used '_' as the lambda parameter, which made '_ = new App()' inside the lambda assign App to the parameter (typed as ApplicationInitializationCallbackParams) instead of being a discard. Rename the parameter to 'p' so the discard works as intended. TODO.md is a new backlog file. Seeded with the shared-parameter-definitions idea: today every Snip carries its parameter definitions inline (env, region, etc.), and the same definition gets duplicated across many Snips. Sketches a shared-by-name model at both CLI and global scope, with local overrides on the Snip, and notes the open design questions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- AllowUnsafeBlocks=true: CsWinRT1030 requires it so the generators can emit the marshalling glue when generic interface types (IServiceProvider, ServiceProvider) cross the WinRT ABI. - Bootstrap: chain the AddSingleton calls to consume the IServiceCollection return value (IDE0058) — clean fluent style, also fewer lines. - MainWindow.ApplyTheme: list ThemePreference.System explicitly so the switch is exhaustive (IDE0072) and keep the underscore arm for defence in depth. - WinUiDispatcher: lazy-init via a GetQueue() method instead of a Queue property; the analyser misreads the '??=' property as 'use auto-property' (IDE0032). A method sidesteps it without changing the semantics. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bootstraps the WinUI 3 head with a load-bearing startup order, a DI container, single-instance handling, and a Mica-clad
MainWindowwith a custom title bar.Boot order
VelopackApp.Build().Run()runs first so it can intercept install / update / uninstall invocations and post-update relaunch.AppInstance.FindOrRegisterForKey("snipdeck"). If we're not the current instance, redirect activation to the primary and exit.Application.Startwith aDispatcherQueueSynchronizationContext, thennew App().The XAML-generated
Mainis disabled (EnableDefaultXamlGeneratedMain=false) so the explicitProgram.csruns.DI container
Bootstrap.Build()synchronously loadsAppConfigfrom the settings store so the snip-store and backup paths are resolved (config value or path-provider default) before the rest of the graph is built. Registered:IPathProvider→WindowsPathProvider(paths under%LOCALAPPDATA%\Snipdeck)IClock,IDispatcher,ISettingsStore,ISnipStore,IBackupServiceAppConfig(initial load)MainWindowMainWindow
ExtendsContentIntoTitleBar+ custom draggable title bar with "Snipdeck"AppConfig.Theme(Light / Dark / System) to the rootFrameworkElementFirst run
If the snip store is empty on launch,
ExamplesSeed.Build()writes a single "Examples" CLI before the window appears.Second-instance behaviour
AppInstance.Activatedis subscribed in theAppconstructor. When a secondary instance redirects activation here, the existingMainWindowis reactivated viaIDispatcher.Enqueueso the marshalling is safe from any thread.Test plan
dotnet test tests/Snipdeck.Core.Tests— 63 passedapp-buildjob compiles the WinUI head underTreatWarningsAsErrors(I can't verify this from Linux)🤖 Generated with Claude Code