Fix the clipped stance row, overlapping alerts, and the missing Linux tray icon - #23
Merged
Merged
Conversation
PlayerSubWindow is pinned to (70, 9, 3, 3) so the themed frame cannot cover the native attack perimeter, which leaves it 114px tall inside the 193px window -- minus whatever the bordered draw template insets. The stance and invocation row is the bottom-most content and was anchored 96..112 from the TOP, so its lower edge fell outside the client area and the row was clipped: Mage Hunter, Defensive, Invocation, Over Channel and Recovery were all unreadable. Anchor both edges to the sub-window's bottom instead. The row keeps its 16px height and now rides 2px above the lower edge, so it stays visible at the 193px minimum and at any size the player resizes to, rather than depending on a draw-template inset nothing in the XML can see. Applied to all seven player-window variants in both skins; the two were already byte-identical here. No window size and no layout profile changes, so saved player layouts are untouched. The audit gains a check that both labels anchor to the bottom, treating an absent anchor tag as the top-anchored default that caused this. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Measured from an in-game screenshot rather than inferred: with the row anchored to the sub-window's bottom, the visible text ended 101px below the sub-window's top edge, which puts PlayerSubWindow's client area at ~116px against the 128px box it occupies. The bordered rounded template eats ~12px that nothing in the XML exposes, so the layout -- authored as if the client were the full box -- never had room for the bottom row. At 193px the client was ~102px while the content above the stance row already ended at 94, leaving 8px for a 16px row. Bottom-anchoring alone could not fix that: it kept the row on screen but slid it under PW_AltAdvGauge, which is listed after it in Pieces and therefore draws over it, so the stance text came out as a 3px sliver. Worse than clipped. PlayerWindow goes to 360x207, which puts the client at ~116px and leaves a 4px gap between the AA gauge and the row. TargetWindow stays 360x193: it has no stance row, and only shared the height for symmetry. The row keeps its bottom anchoring, so the remaining uncertainty in that ~12px border estimate shifts the row rather than hiding it. Regenerates the 24 layout profiles and the Glass payload, and moves the pinned player-frame contracts in restyle_combat, audit_combat_ui and the layout generator to 207. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The control panel is auto-placed on whichever side of the window has room -- above, right, left or below -- and it is click-through, so a player cannot drag it out of the way. positionAlertWindow only knew how to dodge it in the "above" case: companionAbove was the sole avoidance and it is true only when the panel sits entirely above the window. Land the panel to the right, left or below and the alert cards were placed straight over it, hiding the very crowd-control timers the panel exists to show. Move the placement maths into electron/alert-placement.ts and generalise the dodge to every side. "auto" now skips any side the panel occupies, and an explicit Alert location is honoured but pushed clear of the panel rather than drawn over it. With no panel on screen the result is unchanged: auto still prefers above. Covered by scripts/test-alert-placement.cjs, including the panel-above case that used to be the only one handled, so that behaviour cannot regress. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PortableUpdateService resolved the Windows PowerShell path in its constructor, and resolveWindowsPowerShell throws whenever SystemRoot and WINDIR are absent -- which is always, off Windows. main.ts calls initializeUpdateServices() synchronously inside app.whenReady(), ahead of createWindow() and ensureTray(), so that throw aborted the whole ready handler: no engine, no window, no tray icon. The only trace was an UnhandledPromiseRejectionWarning. Resolve the PowerShell path where it is actually used instead -- the Windows portable-replacement path in installAndRelaunch -- so construction is platform-neutral and the failure, when it matters, still surfaces to the caller performing the update. Measured on a KDE session against packaged AppImages, with the stale single-instance lock holder cleared between runs: with this fix engine started, window shown, tray item registered without it none of the three The RC identity overrides are not involved: the passing build carries all of them, including desktopName=loremaster-rc.desktop. scripts/test-updater-startup.cjs builds both update services with SystemRoot and WINDIR removed, so this is caught on any platform rather than only on the machine that runs it. It and the alert-placement suite now run in both CI jobs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The new placement clamped each candidate into the work area before testing whether it fitted, and a clamped rectangle always fits -- so the test was a tautology and "auto" chose "above" no matter how little room was there. With the seed near a screen edge the clamped rectangle landed directly on it. The alert window is always-on-top, so the seed could not be opened, expanded or dragged: analyze and settings became unreachable. Rank candidates before clamping, and treat covering the seed as disqualifying. Every side now offers two candidates -- its natural position and that position pulled back on screen -- and they are ranked together: fully clear first, then on-screen and off the seed, then merely off the seed. Staying off the seed outranks honouring an explicit Alert location, because an unreachable seed costs the whole application. The old space-based preference is restored too: above wins only while it has at least as much room as below. The previous tests missed this because the fixture put the window at (800,500) with room on every side, and asserting "inside the work area" after clamping proved nothing. The suite now sweeps the seed across nine screen positions -- corners, edges and centre -- against every anchor, at the real 128x74 seed and 420x112 alert sizes, and asserts the alert never intersects it: 45 cases. Co-Authored-By: Claude Opus 5 (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.
Three separate defects found while testing the release candidate, all confirmed fixed in-game or against a packaged build.
The stance row was clipped out of the player frame
PlayerSubWindowis pinned to(70, 9, 3, 3)so the themed frame cannot cover the native attack perimeter, leaving it 128px tall inside the window — but its bordered rounded template consumes ~12px, so the client area is ~12px shorter than the box it occupies. The layout was authored as if the client were the full box, so the bottom row (Mage Hunter / Defensive, Invocation / Over Channel / Recovery) never had room and was cut off.Measured from an in-game screenshot rather than inferred: the visible text ended 101px below the sub-window's top edge, which is what pinned the client height down.
PlayerWindowgoes 360x193 → 360x207, which leaves a 4px gap between the AA gauge and the row.TargetWindowstays 193: it has no stance row and only shared the height for symmetry.Applied to all seven player-window variants in both skins, which were byte-identical here. Regenerates the 24 layout profiles and the Glass payload, and moves the pinned contracts in
restyle_combat,audit_combat_uiand the layout generator.Anchoring alone was tried first and made it worse: it kept the row on screen but slid it under
PW_AltAdvGauge, which is listed after it inPiecesand therefore draws over it. The height is what it actually needed.Alert cards landed on the crowd-control panel
The control panel is auto-placed on whichever side has room — above, right, left or below — and is click-through, so it cannot be dragged clear.
positionAlertWindowonly knew how to dodge it in the "above" case, so the other three placements put alert cards straight over the timers the panel exists to show.Placement moves to
electron/alert-placement.tsand the dodge is generalised to every side.autoskips any side the panel occupies; an explicit Alert location is honoured but pushed clear rather than drawn over. With no panel on screen the behaviour is unchanged.No tray icon on Linux
PortableUpdateServiceresolved the Windows PowerShell path in its constructor, andresolveWindowsPowerShellthrows wheneverSystemRootandWINDIRare absent — always, off Windows.main.tscallsinitializeUpdateServices()synchronously insideapp.whenReady(), ahead ofcreateWindow()andensureTray(), so that throw aborted the entire ready handler. No engine, no window, no tray icon, and the only trace was anUnhandledPromiseRejectionWarning.Introduced by the upstream secure-updates merge, which is why v0.3.4 has a tray and everything since does not. The path is now resolved where it is used, in the Windows-only
installAndRelaunch.Measured on a KDE session against packaged AppImages, with the stale single-instance lock holder cleared between runs:
The release-candidate identity overrides are not involved — the passing build carries all of them, including
desktopName=loremaster-rc.desktop.Tests
scripts/test-updater-startup.cjsbuilds both update services withSystemRootandWINDIRremoved, so the startup crash is caught on any platform rather than only where it happens to run.scripts/test-alert-placement.cjscovers the placement maths, including the panel-above case that used to be the only one handled. Both now run in both CI jobs. The combat audit gains a check that the stance labels stay bottom-anchored, treating an absent anchor tag as the top-anchored default that caused the original bug.Quality gate ALL PASS. Player-frame height and tray icon both confirmed in-game.
🤖 Generated with Claude Code