Fix Windows notification color inversion#211
Conversation
492bae9 to
2520cbd
Compare
rtibblesbot
left a comment
There was a problem hiding this comment.
Clean fix for the Windows notification icon color inversion (#184). Replaces legacy ShowBalloon() with wx.adv.NotificationMessage, which handles icon rendering correctly across Windows themes. CI passing.
- praise: Good defensive fallback chain and error handling throughout
@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly
How was this generated?
Reviewed the pull request diff checking for:
- Correctness: bugs, edge cases, undocumented behavior, resource leaks, hardcoded values
- Design: unnecessary complexity, naming, readability, comment accuracy, redundant state
- Architecture: duplicated concerns, minimal interfaces, composition over inheritance
- Testing: behavior-based assertions, mocks only at hard boundaries, accurate coverage
- Completeness: missing dependencies, unupdated usages, i18n, accessibility, security
- Principles: DRY (same reason to change), SRP, Rule of Three (no premature abstraction)
- Checked CI status and linked issue acceptance criteria
- For UI changes: inspected screenshots for layout, visual completeness, and consistency
| logging.error( | ||
| f"Failed to show notification with NotificationMessage: {notification_error}" | ||
| ) | ||
| self._show_legacy_notification(title, message, timeout) |
There was a problem hiding this comment.
✅ Resolved — addressed in the current code.
praise: Well-structured fallback chain: NotificationMessage → ShowBalloon → MessageBox. Each layer catches specific exceptions and logs before falling through, so notifications degrade gracefully on older Windows versions or unexpected runtime errors.
| # Cached icon used for notifications | ||
| self._tray_icon = None | ||
| # Keep reference alive while shown | ||
| self._last_notification = None |
There was a problem hiding this comment.
✅ Resolved — addressed in the current code.
praise: Good call keeping _last_notification as an instance attribute — prevents the NotificationMessage object from being garbage-collected while the notification is still visible.
2520cbd to
8519ef3
Compare
|
Hi @rtibbles - unfortunately the app is not starting in both Windows 11 and 10, seems that this is the relevant error in the logs: Logs: logs.zip |
The tray balloon rendered the Kolibri icon as a color negative in Windows light theme (correct in dark theme, and correct in the tray itself). Every entry in kolibri.ico was PNG-compressed, including the 16-48px sizes. The Shell_NotifyIcon balloon path can't decode PNG-in-ICO, so it falls back to XOR-mask drawing: XOR against a light background inverts the colors, XOR against a dark one leaves them intact. Re-encode the small sizes (16/24/32/48) as uncompressed BMP; keep 64/128/256 as PNG. Renders identically everywhere. Fixes #184 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018nCc7x3MRihUCQFUUP46jc
8519ef3 to
4303712
Compare
🔵 Review postedLast updated: 2026-07-04 01:42 UTC |
rtibblesbot
left a comment
There was a problem hiding this comment.
3 of 3 prior findings resolved — the prior approach (NotificationMessage) was abandoned entirely in favor of a binary icon re-encode, so the Timeout_Default crash and both praise comments on that removed code are moot.
Still open (not caused by this PR, but blocking a green merge):
- important: CI's "All file linting" (
uv-lockprek hook) is failing, but this predates this branch — confirmed the same job fails onmain's tip (a9f1e13, this branch's merge-base) via the check-runs API.pyproject.toml'sexclude-newer = "7 days"is a rolling window, souv.lockneeds periodic re-resolution independent of this diff. Nothing in this PR (kolibri.icoonly) can fix it — needs auv lockregen onmainand a rebase. - suggestion: Since this PR no longer touches
taskbar_icon.py, @pcenov's crash report was against the abandoned approach. Worth a short comment confirming they've re-tested against this narrower icon-only fix.
Verified the re-encoded kolibri.ico directly: 16/24/32/48px are now raw BMP (matching the Shell_NotifyIcon legacy balloon path that caused the original inversion), 64/128/256px remain PNG. Decoded all 7 sizes — consistent yellow/blue colors, no inversion.
Prior-finding status
RESOLVED — src/kolibri_app/taskbar_icon.py — NotificationMessage.Timeout_Default crash reported by pcenov (approach replaced with icon re-encode, not patched)
RESOLVED — src/kolibri_app/taskbar_icon.py:115 — praise: defensive NotificationMessage → ShowBalloon → MessageBox fallback chain (code removed, no longer applicable)
RESOLVED — src/kolibri_app/taskbar_icon.py — praise: _last_notification instance attribute (code removed, no longer applicable)
@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly
How was this generated?
Compared the current PR state against findings from a prior review:
- Retrieved prior bot reviews via the GitHub API
- Classified each prior finding as RESOLVED, UNADDRESSED, ACKNOWLEDGED, or CONTESTED
- Only raised NEW findings for newly introduced code
- Ran the same phased review passes as a first review (core, frontend/backend lenses, manual QA when required)
- Synthesized one review from the passes and chose the verdict from the findings, CI status, and QA evidence
Summary
Fixes the Kolibri tray-notification icon rendering as a color negative on Windows light theme (#184).
Root cause: every entry in
kolibri.icowas PNG-compressed, including the small 16–48px sizes. TheShell_NotifyIconballoon path can't decode PNG-in-ICO and falls back to legacy XOR-mask drawing — XOR against a light background inverts the colors, XOR against a dark background leaves them intact. This matches the symptom exactly: inverted in light theme, correct in dark theme, correct in the tray icon itself.Fix: re-encode the small sizes (16/24/32/48) as uncompressed BMP; keep 64/128/256 as PNG. Icon renders pixel-identically everywhere; no code change.
Testing
On Windows 10/11,
Settings > Personalization > Colors, set mode to Light. Launch Kolibri and wait for the "Kolibri is starting…" / "Kolibri Ready" notification. The Kolibri logo should show its correct colors (yellow background, blue bird) — no longer inverted.