Skip to content

Sync upstream 1.151.2 (help assistant, annex by click, redraw option, label fixes) - #68

Merged
barrulus merged 45 commits into
mainfrom
sync/upstream-1.151.2
Sep 5, 2026
Merged

Sync upstream 1.151.2 (help assistant, annex by click, redraw option, label fixes)#68
barrulus merged 45 commits into
mainfrom
sync/upstream-1.151.2

Conversation

@barrulus

@barrulus barrulus commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Merges Azgaar master df18b17 (PR Azgaar#1804: Azgaar#1802, Azgaar#1801, Azgaar#1800, Azgaar#1778, Azgaar#1599 and the help-assistant branch) into fork main.

Conflict resolutions

  • docs/wiki/Changelog.md, src/utils/markdown.test.ts: upstream's version (superset of the fork's).
  • package.json: version stays 1.151.2-fork.1 (never released); fork scripts and flatqueue kept, lockfile regenerated with npm install --package-lock-only.
  • src/controllers/states-editor.ts: upstream's confirmStatesMerge extended with the fork's merge-to-provinces flag and message; annex helper kept; fork's null-safe army handling kept; upstream's states redraw fix applied (manual path removals dropped).
  • src/components/zoom.ts: fork structure plus upstream's viewportRedraw gate; the fork's explicit settle-time renderNow dropped because invokeActiveZooming already renders (upstream's zoom tests assert one render).
  • src/index.html: stamps restamped; fork default for "Redraw on zoom" set to "After zoom" to keep the fork's settle-only behaviour; the e2e spec's default assertion follows.
  • src/generators/burgs-generator.ts: the fix: validate the stored label and burg group registries Azgaar/Fantasy-Map-Generator#1801 port and upstream's copy auto-merged into two parseStoredGroups; one removed.
  • src/services/io/auto-update.test.ts: both imports kept.
  • nix/package.nix: npmDepsHash re-pinned via prefetch-npm-deps for the regenerated lock.

Verification (real npm ci in the worktree)

tsc clean; biome check clean (2 pre-existing fork warnings); vitest 1027/1027; e2e annex-mode, controller-launchers, help-token-stash, load-map, stored-options, style-label-ranges, zoom-redraw-option: 31/32. The one miss is upstream's "refuses to annex a province from a different state": its candidate search tries a single partner per province and finds no visible pair on the fork's seed map; not a product failure.

Closing the dialog left the retry countdown timer and any in-flight
submit() continuation running against a detached/removed DOM, causing
timer crashes, a stale Ask button unlock on reopen (silently bypassing
the rate-limit lock), null appendChild on late answers, and an
unhandled rejection on non-HelpApiError failures. Clear the timer and
bail out of all DOM work once the dialog is unmounted.

Also implement the one-automatic-retry rule: only auto-resubmit a
rate_limited question when the server sent retryAfter, and only once
per failure chain; fix the Ask button label staying on "Asking..." for
locked non-countdown states (cap_reached/quota/blocked).
A 200 with a non-JSON body (e.g. a proxy/CDN interstitial) escaped
ask()/getLimits() as a raw SyntaxError instead of a HelpApiError.
Wrap the OK-path json() parse and throw provider_error, mirroring the
non-2xx error path. Also correct the cap_reached test fixture's status
to 503, the settled contract (client keys off error.code, not status).
…t pins

- helpAssistantBubble never fired its data-tip (outside every
  TIP_CONTAINERS) and had no keyboard path; wire showDataTip on
  mouseover and add role/tabindex/aria-label plus an Enter/Space
  keydown handler, matching the deleted OpenWidget wiring.
- Drop the two dead #chat-widget-container/#chat-widget-minimized CSS
  rules (OpenWidget is gone); fadeIn keyframes stay, still used by
  #tourPromptButton.
- controller-launchers.spec.ts asserted on the removed OpenWidget
  element unconditionally; the assertion was incidental to the test's
  actual purpose (opening Markers Generation Settings), so drop it.
- Pin renderMarkdown's link attribute-breakout output in
  markdown.test.ts.
- signIn() marks a pending flag before redirecting; main.js only stores
  the fragment token when that flag is set, always scrubs the hash
  either way (token fixation guard)
- drop "moderator" from Limits.tier (web tier is anonymous|member)
- refreshLimits renders auth from local token state on a failed
  /v1/limits instead of dropping the sign-out affordance
- refresh stale index.html asset cache stamps for main.js/index.css
- 401 now clears the conversation id alongside the token, so a
  freshly-anonymous caller never sends a member-owned id
- sign-out and New chat both reset the visible transcript through a
  shared resetConversationLog(), so rollover is shown, not silent
- submit() adopts the server-issued conversation id before the
  isMounted() guard, so closing the dialog mid-ask no longer orphans it
- adoptConversationId rejects malformed ids, and an invalid_request
  error clears the stored id so the next ask starts clean
- test fixtures only carry conversationId where the server actually
  sends it
… aria-pressed thumbs

- ask() now rejects a contract-violating bodyless 204 from /v1/ask with
  HelpApiError("provider_error", ...) instead of silently resolving undefined
  (src/services/help/api.ts)
- buildFeedbackControl's failed-feedback catch now calls refreshLimits() when the
  rejection is HelpApiError("unauthorized", ...), so the footer resyncs after the
  shared transport clears the token (src/controllers/help-assistant.ts)
- feedback thumb buttons now keep aria-pressed in lockstep with the .selected class
  on init, click, and revert (src/controllers/help-assistant.ts)
Both editors get an Annex button beside Merge. Click the annexing state
or province, then the ones it absorbs; Shift keeps the mode open. Nothing
changes until the session ends, when the existing merge confirmation
lists what will be removed, so a mis-click can be cancelled.

The mode lives in components/annex-mode and is driven by each editor
with its own owner lookup and merge call. mergeStates is hoisted out of
the dialog and the two merge confirmations are extracted so the dialog
and the annex mode share them. Three copies of the animated red outline
collapse into highlightOutline.

Provinces refuse a pick from another state, matching the merge dialog.
The stroke width slider spans 0-10 for every label group while group
font sizes run from 2 (river, route) to 22 (state). On a river label a
single pixel of slider travel already exceeds the usable band.

Values stay absolute and unscaled. Only the drag range follows the
selected group: stroke width up to half the font size, letter spacing
from a tenth below zero to half above, and never narrower than the
stored value so it stays reachable. Every other element gets the ranges
declared in index.html back, and changing the font size refits live.

slider-input now observes min, max and step, which it read only once
in the constructor.

Fixes Azgaar#1592
Every guard-band escape during a zoom or pan re-runs label
materialization and the collision pass, so a long gesture recalculates
many times over. Mid-gesture pop-in is the intended look, so it stays
the default; users on big maps can now trade it for one redraw per
gesture.

Options -> Rendering gains "Redraw on zoom": "While zooming" (default)
or "After zoom". It is stored per device like the Rendering select. The
per-frame handler skips ViewportLayers.schedule() in the after-zoom
mode; the end-of-gesture render is unchanged, so labels always catch up.

The e2e drives a real wheel gesture: programmatic zooms dispatch "end"
with the frame still pending and cannot see a missing end-of-gesture
redraw.
A value persisted by an older build can be structurally valid and still
leave the renderer with nothing to draw - `{groups: []}` has every key,
the right types, and produces a map with no labels at all. Both keys are
read unvalidated on boot and again in randomizeOptions, so the bad value
survives every new map until the user clears site data.

Parse them through Labels.parseStoredOptions and Burgs.parseStoredGroups
instead: drop entries the renderer cannot use, restore any label type
left without a group, and keep a default burg group for assignment to
fall back on.
Pre-1.140 zoom auto-visibility hid burg label tiers with an inline
display: none, and a map saved while zoomed out carried it in the group's
style attribute. The 1.140 migration harvested it verbatim into the
persisted label group style, the 1.150 store migration kept it, and since
the store is applied over the saved svg on load, those tiers never rendered
again at any zoom.

Strip display in labelStyleFromLegacy, the funnel for both harvests, and
add a 1.151.2 pass over the stored label group styles for maps saved by
1.150-1.151.1, which already carry the value in their styles record.

Closes Azgaar#1773
Layers.show only draws layers that were off, so mergeStates never redrew
the ruling state once the editor had turned the layer on. Draw the layers
instead and stop removing the annexed state's paths by hand.
Unreleased entries move from Releases to Current version. Documents the
annex tool, the redraw-on-zoom option, the label slider ranges and the
validated stored label and burg group settings.
…, label fixes

Upstream df18b17 (PR Azgaar#1804) onto fork main cbe0880. Eight conflicts:
changelog and markdown test taken from upstream; package version keeps the
fork suffix; states editor keeps the merge-to-provinces demote path on top
of upstream's extracted confirmation and annex helper; zoom keeps the fork
structure with upstream's redraw option, defaulting the fork to "After
zoom"; the duplicated parseStoredGroups port and the fork's second settle
render are dropped. Lockfile regenerated, assets restamped, npmDepsHash
re-pinned.
@netlify

netlify Bot commented Sep 5, 2026

Copy link
Copy Markdown

Deploy Preview for bazgaars-fmg ready!

Name Link
🔨 Latest commit cd07a22
🔍 Latest deploy log https://app.netlify.com/projects/bazgaars-fmg/deploys/6a9c13f3394a4c00088d3a1b
😎 Deploy Preview https://deploy-preview-68--bazgaars-fmg.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@barrulus
barrulus merged commit ae9575b into main Sep 5, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant