Conversation
Bundled minor release instead of two separate patches, per the new "don't ship a release for every fix" cadence. - Single-instance launcher: re-launching while the app is in the tray no longer pops an "already running" dialog. The secondary process signals a named EventWaitHandle, grants ASFW_ANY foreground rights, and exits silently; the primary's listener thread dispatches to the UI and surfaces the window from offscreen via SetForegroundWindow. - Memory Stats card: switched the inner layout from a top-anchored StackPanel to a 3-row Grid (Auto / * / Auto) so the KPI block sits vertically centered in the cell and the Total / Free strip pins to the bottom — eliminates the ~40 % dead band that appeared when the sibling Standby Purge card stretched the row taller. - Clearable subtitle FontSize bumped 10 → 12 for legibility next to the 28-pt KPI. Version metadata bumped in csproj + Setup.iss + winget manifests (InstallerSha256 reset to a placeholder; the release pipeline fills it after build-installer.ps1 hashes the produced .exe). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The locale yaml shipped "License: Proprietary" while the repository itself is MIT-licensed. The mismatch surfaced as confusing metadata on the winget package page. Aligns with LICENSE; also adds LicenseUrl so users can read the terms inline from winget output, and fills in the missing copyright year. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Foundation for the next 11 tasks (hotkey + tray toggle + notify prefs + idle-only auto-purge). Pure data + strings — no behavior change yet; subsequent tasks wire the UI and runtime guards. - AppSettings: 7 new fields with sensible defaults (notify flags default ON for upgrade parity, idle threshold 5 min, hotkeys Ctrl+Alt+P / Ctrl+Alt+T) - SettingsService: persist and round-trip the new fields; ints via DWORD, hotkeys as REG_SZ so a future capture-textbox can edit them in-place - Strings (en + tr): 10 new keys for Memory Purges KPI, idle-only controls, Notifications section, Hotkeys section - Plan: docs/superpowers/plans/2026-06-28-v2.1.0-bundle.md Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- RegisterHotKey / UnregisterHotKey for system-wide chord routing - GetLastInputInfo + LASTINPUTINFO struct for idle-gate auto-purge - MOD_* flag constants + WM_HOTKEY message id Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bottom strip becomes Total | Free | Purges. PurgeCount binds via the inherited MainViewModel DataContext; AppFg colour to avoid competing with Total's accent yellow or Free's success green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The "× N" chip on the right of the header was asymmetric with the left card and pushed the title off-centre. Count now lives on the Memory card's bottom strip; the StandbyPurge header is just the title, matching MemoryStats / GameMode / Timer header style. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- IIdleMonitor wraps GetLastInputInfo. Survives lock screen — the kernel keeps ticking, which matches Windows' "Away" semantics. - IMemoryMonitorService gains AutoPurgeIdleOnly + IdleThresholdMs. Loop body gates the existing purge condition with: !IdleOnly || TimeSinceLastInput >= IdleThresholdMs. Default OFF → no behaviour change for existing users on upgrade. - MainViewModel exposes both as ObservableProperty; ApplySettings, SyncMonitorThresholds, BuildCurrentSettings, and partial change handlers all extended. Idle-threshold uses debounced persist (same TextBox-keystroke pattern as Standby / Free limits). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New row sits between the title and the AUTO PURGE master toggle. Greyed via IsEnabled binding when AUTO PURGE is off (the gate has no effect without the master switch). Minutes input mirrors the Standby / Free limit pattern (Width=78, Height=26, FontSize=12) for visual symmetry. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- ITrayIconService grows ToggleRequested distinct from ShowRequested: Show is "always surface" (right-click menu); Toggle is "flip" (left-click / double-click). - TrayIconService routes MouseClick.Left + DoubleClick to Toggle. - MainWindow exposes IsOffscreen so App can decide which way to flip. - App.ToggleMainWindow uses SurfaceMainWindow (foreground promote) when hidden, HideOffscreen when visible. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- App caches the latest AppSettings via MainViewModel.SettingsPersisted so balloon guards don't hit the registry on every event. - Each of the three balloon handlers returns early when its NotifyOnX flag is false. Defaults stay ON, so users who never open Settings see no behaviour change. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previous commit added an AppSettings? field but forgot to import StandbyAndTimer.Core.Models, so Release build failed with CS0246. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- SettingsViewModel: 5 new [ObservableProperty] fields (3 notify flags + 2 hotkey display strings). Initialize signature grows to take all of them; partial change handlers fire SettingsChanged so PersistSettings runs on every toggle. - MainViewModel.ApplySettings + BuildCurrentSettings round-trip the new SettingsViewModel state to/from AppSettings. - SettingsPanelView: Notifications section (3 DarkCheckBoxStyle checkboxes) and Hotkeys section (read-only labels showing the current bindings; rebind UI parked for v2.2) inserted between Theme picker and Backup section. Row count grew 28 → 42 but the * Logs row absorbs the height — no overall layout shift, no outer scrollbar. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- HotkeyBinding record + Parse("Ctrl+Alt+P") covers Ctrl/Alt/Shift/Win
modifiers, A-Z / 0-9 alphanumeric keys, and F1-F24. Returns null on
malformed input so callers can log + fall back.
- IHotkeyService AttachTo(hwnd) + Register(id, binding, handler) +
Unregister(id) + Dispose. Replaces prior registration for the same
id so a future Settings rebind UI is safe.
- HotkeyService installs an HwndSource.AddHook that routes WM_HOTKEY
to the matching handler. MOD_NOREPEAT is auto-OR'd into the mask so
holding the chord doesn't fire the handler at keyboard-repeat rate.
- Registered in DI as a singleton.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- MainWindow.WindowHandle: exposes the HwndSource-backed HWND. Non-zero after Show() (or HideOffscreen, which internally Show()s), so it's available at the point App attaches HotkeyService. - App.OnStartup: AttachTo(WindowHandle) then RegisterHotkeyFromSetting for both purge + timer. Hotkey strings come from saved settings so a power user can rebind them via the registry today; the Settings UI is read-only for v2.1.0. - App.OnExit: dispose HotkeyService BEFORE the HWND tears down so the OS releases each RegisterHotKey cleanly — without this, a fast restart would fail with "hot key already registered." - Handlers dispatch via Application.Current.Dispatcher.BeginInvoke to avoid racing the WPF binding system off-thread. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Each of the three KPI cells now anchors its label + value to the matching side of its column (Left for Total, Center for Free, Right for Purges) instead of all three flushing left. The row breaks cleanly into thirds visually, matching the bottom-strip pattern used in the rest of the dashboard. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User found 12pt still small next to the 28pt KPI. Top margin nudged 3 → 4 to keep the visual gap proportional. Co-Authored-By: Claude Opus 4.7 <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
Bundled minor release replacing what would otherwise have been two patch bumps. First release under the new "batch fixes, don't ship per-commit" cadence.
EventWaitHandle, grantsASFW_ANYforeground rights, pulsesSet(), and exits silently. The primary's background listener dispatches to the UI thread and surfaces the window viaShowFromOffscreen()+SetForegroundWindow(hwnd). CTS-cancelled, disposed cleanly inOnExit.StackPanelto a 3-rowGrid(Auto/*/Auto). KPI block sits centered in the slack the sibling Standby Purge card forces on the row, and the Total / Free strip pins to the bottom — eliminates the ~40% dead band at the bottom of the box.Files
App.xaml.cs+AppConstants.cs+NativeMethods.cs— single-instance plumbing (namedEventWaitHandle,AllowSetForegroundWindow,SetForegroundWindow)Views/Cards/MemoryStatsCard.xaml— layout / typographyStandbyAndTimer.csproj,installer/Setup.iss,winget-manifests/*.yaml— version bumped to 2.1.0,InstallerSha256reset to placeholder (the release pipeline updates it afterbuild-installer.ps1).Release plan after merge
.\build-installer.ps1 -Version 2.1.0to produce the .exe and the SHA256.v2.1.0with the installer attached.InstallerSha256(matches the pattern used for every prior release).Test plan
dotnet build -c Release) — 0 warnings / 0 errors..exelaunch → 3 sec later still one process, no MessageBox.🤖 Generated with Claude Code