From 51888ec538aa71c7c12231c6a6fdcd322cb45191 Mon Sep 17 00:00:00 2001 From: Jackie Chen Date: Wed, 5 Aug 2026 20:34:40 +0800 Subject: [PATCH] feat: battery voltage history by charge level, sub-watt tray power (v1.1.6) Records the battery driver's measured terminal voltage each time the integer battery percentage changes, and plots the resulting 0-100% curve on a new Battery Voltage History tab. Per-percentage average/min/max voltage, change count and last-recorded time are persisted in LocalAppData and shown in an exact-value table alongside the chart. Unobserved percentages are left as gaps rather than interpolated, and a voltage is only recorded when IsVoltageMeasured is true, so the internal nominal voltage used for power math never reaches the curve. Also fixes the tray icon rounding every rate to an integer, which rendered a real 0.1-0.9 W flow as "0". Sub-watt rates now keep one decimal place; the integer and "99+" rules above 1 W are unchanged. Co-Authored-By: Claude Opus 5 --- .github/release-notes/v1.1.6.md | 27 +++ AI_HANDOFF.md | 91 +++++++- MainWindow.xaml | 90 +++++++- MainWindow.xaml.cs | 207 ++++++++++++++++++ Models/BatteryVoltageHistoryPoint.cs | 110 ++++++++++ Services/BatteryVoltageHistoryService.cs | 179 +++++++++++++++ Services/DynamicTrayIconService.cs | 22 +- Services/LocalizationService.cs | 20 ++ WinBatLens.csproj | 10 +- .../BatteryVoltageHistoryPointTests.cs | 46 ++++ .../TrayIconPowerFormattingTests.cs | 24 ++ 11 files changed, 807 insertions(+), 19 deletions(-) create mode 100644 .github/release-notes/v1.1.6.md create mode 100644 Models/BatteryVoltageHistoryPoint.cs create mode 100644 Services/BatteryVoltageHistoryService.cs create mode 100644 tests/WinBatLens.Tests/BatteryVoltageHistoryPointTests.cs create mode 100644 tests/WinBatLens.Tests/TrayIconPowerFormattingTests.cs diff --git a/.github/release-notes/v1.1.6.md b/.github/release-notes/v1.1.6.md new file mode 100644 index 0000000..7fd7f3f --- /dev/null +++ b/.github/release-notes/v1.1.6.md @@ -0,0 +1,27 @@ +## WinBat Lens v1.1.6 + +This release adds a battery voltage curve recorded against state of charge, and +fixes a tray icon that hid real sub-watt power flow. + +### Highlights + +- **New "Battery Voltage History" tab.** The monitor records the battery + driver's measured terminal voltage each time the integer battery percentage + changes, and plots the resulting 0–100% curve. +- Per-percentage average, minimum and maximum voltage, change-event count and + last-recorded time are kept in an exact-value table alongside the chart, with + a clear action. +- The history is persisted per user in LocalAppData, so the curve keeps + building across sessions. +- Percentages that have never been observed are left as gaps in the curve + rather than interpolated — an unmeasured voltage is never drawn as if it had + been read. +- Only voltages the battery driver actually reported are recorded. The internal + nominal voltage used for power math is excluded. +- **Tray icon: sub-watt power is no longer rounded away.** A real charge or + discharge rate between 0.1 W and 0.9 W used to render as `0`, hiding the fact + that power was flowing. Rates below 1 W now show one decimal place; whole-watt + and `99+` display above 1 W is unchanged. + +The published executables are unsigned. Windows SmartScreen may show a warning +on first launch. diff --git a/AI_HANDOFF.md b/AI_HANDOFF.md index f57e44a..1d56db1 100644 --- a/AI_HANDOFF.md +++ b/AI_HANDOFF.md @@ -1,10 +1,58 @@ # Project State & Handoff -## v1.1.5 release preparation (2026-08-05) +## v1.1.6: battery voltage history by percentage (2026-08-05) + +Added a battery voltage history feature. The monitor records a real +battery-driver voltage only when the integer battery percentage changes; the +same percentage is ignored on subsequent one-second polls. The first +observation seeds a percentage that has no prior record, while a percentage +seen again after the battery moves is aggregated as another change event. + +`BatteryVoltageHistoryService` persists per-percentage average/minimum/maximum +voltage, event count, and last timestamp in the user's LocalAppData. The new +Battery Voltage History tab plots the observed 0-100% curve, leaves gaps for +unmeasured percentages, and includes an exact-value table plus clear action. +The chart never uses `RealTimePowerState.BatteryVoltageV` when +`IsVoltageMeasured` is false, because that state can carry an internal nominal +voltage used only for power math. + +Shipped together with the sub-watt tray icon fix below as **v1.1.6**; release +notes are in `.github/release-notes/v1.1.6.md`. + +### Review pass before release + +Four defects were found and fixed in the new tab before publication, all in +presentation rather than in the recorded measurements: + +1. **The vertical gridlines did not line up with the data.** They were drawn + across the whole container in tenths (`width/10*i`), but the curve is + plotted into an inset area (`plotLeft = 44`, `plotRight = 8`) that leaves + room for the Y-axis labels. `DrawVoltageChartGridlines` now takes + `plotLeft`/`plotWidth` and draws `i = 0..10` across the plot area, so a + gridline sits exactly under the percentage it marks and the plot's own + 0%/100% edges are visible. +2. **The 25% and 75% X-axis labels were in the wrong place.** Five equal + columns with the outer two edge-aligned put their centres at 30% and 70%. + The end columns are now `0.5*`, which lands every label on its true + position. +3. **`LastRecordedAt` was bound raw**, so the column rendered a + culture-dependent `DateTime.ToString()` instead of the app's + `yyyy-MM-dd HH:mm:ss` convention. A `LastRecordedAtText` property was added + (and change-notified from `AddSample`) to match `PowerHistoryRecord`. +4. **The XAML placeholder text and the samples-column header disagreed with + the localization strings** they are overwritten with at runtime — the header + said 樣本數 where the string is 變化次數, which is the more accurate name for + what is counted. + +Validation after the fixes: Debug and Release solution builds passed with +`-warnaserror` at 0 warnings / 0 errors, `dotnet test` passed 17/17, and +`git diff --check` passed. + +## v1.1.5 release and publication (2026-08-05) The post-v1.1.4 background-startup and comprehensive audit changes are being -prepared for publication as v1.1.5. The project version is now 1.1.5 and the -release notes are in `.github/release-notes/v1.1.5.md`. +published as v1.1.5. The project version is 1.1.5 and the release notes are in +`.github/release-notes/v1.1.5.md`. The intended release scope is the complete existing working-tree change set: background startup, tray warmup/idle behavior, removal of unsupported or dead @@ -23,8 +71,31 @@ three assets; they are unsigned by design in this environment: - `WinBatLens_v1.1.5_Setup_x64.exe`: SHA-256 `B4F5C013BA3F6CEAF1D1E917C068304A2CD993E3CB8FE90A2A830DAFA4DDA4B9` -The ZIP contains `WinBatLens.exe`, `README.md`, and `LICENSE`. Publication to -GitHub is the remaining step. +The ZIP contains `WinBatLens.exe`, `README.md`, and `LICENSE`. PR #8 was merged +to `main` at `c9fdbed`, tag `v1.1.5` triggered Release workflow run +`30962533960`, and the normal GitHub Release is published at +`https://github.com/nojackno2-ctrl/WinBat-Lens/releases/tag/v1.1.5`. + +The GitHub runner rebuilt the release assets, so the authoritative downloaded +asset hashes are: + +- `WinBatLens_v1.1.5_Portable_x64.exe`: SHA-256 + `1c8e0757439a0bde196149022bf048f6f7faf91574ff5496d640a07abaf798c9` +- `WinBatLens_v1.1.5_Portable_x64.zip`: SHA-256 + `1cdd0edf0908228021ef1ae34e0beec903c670fab2dc4b72ca889d16d6b35d2a` +- `WinBatLens_v1.1.5_Setup_x64.exe`: SHA-256 + `c66ca8fe3e8928240917a29d4df8a4364c2b1a3fe571fe443244fd973164cd76` + +## Sub-watt tray icon power display (2026-08-05) + +`DynamicTrayIconService` previously rounded every measured charge/discharge +rate to an integer before drawing it. A real rate between 0.1W and 0.9W was +therefore rendered as `0`, hiding the fact that power was flowing. The shared +`FormatWattageForIcon` formatter now keeps one decimal place below 1W while +preserving the existing integer and `99+` display rules at higher values. + +Added `TrayIconPowerFormattingTests` covering sub-watt, whole-watt, and +overflow formatting. Released as part of v1.1.6. ## v1.1.4 released (latest) @@ -131,10 +202,12 @@ run during this pass. ## Branch consolidation (2026-08-05) -After refreshing `origin`, every branch had no commits outside `main`. The -already-merged local `feat/show-version-and-handle-duplicate-launch` branch -and remote `claude/memory-cpu-optimization-p0z5ve` branch were deleted. Only `main` remains locally and on `origin`; the working-tree audit changes remain -uncommitted. +After refreshing `origin`, `codex/v1.1.5-release` was confirmed to have no +commits outside `main`; `main` already contained its release commit via the +`c9fdbed` merge. The local and `origin` copies of that already-merged branch +were deleted. Only `main` remains locally and on `origin`. The battery-voltage +history and sub-watt tray-formatting changes in the working tree remain +uncommitted and were preserved. ## Complete Traditional Chinese XML Documentation Pass (2026-08-05) diff --git a/MainWindow.xaml b/MainWindow.xaml index dead3f8..0ceda8d 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -505,7 +505,91 @@ - + + + + + + + + + + + + + + + +