Skip to content

feat: WYSIWYG drag-to-place flight plan on PNG export#378

Draft
msupino wants to merge 24 commits into
devfrom
wysiwyg-flight-plan
Draft

feat: WYSIWYG drag-to-place flight plan on PNG export#378
msupino wants to merge 24 commits into
devfrom
wysiwyg-flight-plan

Conversation

@msupino

@msupino msupino commented May 27, 2026

Copy link
Copy Markdown
Owner

Summary

Replaces the 6 placement buttons (None / ↖TL / ↗TR / ↙BL / ↘BR / Custom) with a drag-to-place WYSIWYG zone inside the Export PNG modal.

  • Preview zone shows a scaled A3/A4 rectangle with the same aspect ratio as the page frame
  • Click anywhere in the zone to place the flight plan table at that position
  • Drag the box to reposition; the mini table renders real leg data (From/To/Hdg/Dist/Spd/Alt/Time)
  • "× Remove" button clears the placement
  • Zone shows "Set A3/A4 page size to enable" hint when no page frame is active
  • On export: planWysiwygPos {xPct, yPct} → canvas pixel coords (xPct × frame.w × scale)
  • Drag event listeners are removed on modal close (no leak)

Tests

Updated export-png-options.spec.js — old tests clicked TL/BR/None buttons; new tests click the zone, verify .export-wysi-box appears/disappears, and verify Export still produces a PNG. 243/243 passing.

Branched from

dev-planPin-v2 (#338 — placement picker). This PR extends that work.

msupino and others added 16 commits May 27, 2026 08:53
Replaces the entire pin-button + drag/resize flow with a single
6-button row inside the Export PNG modal:

  Flight plan placement:  [ None ] [↖ TL] [↗ TR] [↙ BL] [↘ BR] [Custom…]

- None  → no plan drawn on export
- TL/TR/BL/BR → wireframe placeholder snaps to that corner of the
  current page frame (A3/A4) or the viewport when no frame is set
- Custom → centred placeholder, fully draggable and resizable
- Selected option highlights yellow; user can re-pick freely without
  leaving the export dialog

Replaces all of:
- the .modal-pin button + planPinned state + PLANPIN_KEY
- pin-modal drag handlers
- four-corner resize handles on the flight-plan modal
- font auto-shrink + ResizeObserver hooks
- navaid.planPin / planW / planH localStorage (auto-cleared on open
  so old installs migrate silently)
- modal.pinned CSS (replaced with plan-placeholder rules)

Canvas drawFlightPlanTable always uses S.fpHeadersShort now — no
DOM-class check for pinned, no headers branch.

Test set updated: pin tests dropped; new tests cover pin-button gone,
stale-storage cleanup, corner placement creates a placeholder, None
removes it, Export with a placement still downloads a PNG.

Co-Authored-By: Claude Sonnet 4.7 <noreply@anthropic.com>
…larger font

The PNG-embedded plan rendered as a dark-grey block with near-invisible
0.5 px grid lines, capped at 13 px font. It looked like a UI overlay
dropped onto the chart, not a printed flight log.

Redraw as a paper table:
- White background, dark text (#1a1a1a)
- Light grey header row (#e8e6e1) and total row (#f0eee9) for structure
- Off-white stripe (#f7f5f0) on every other data row for fast row-tracking
- Grid lines drawn in one pass on top of cell backgrounds in a clear
  warm-grey (#7a7470) at 0.75-1 px — readable when printed
- Half-pixel offsets on grid coords for crisp lines on retina output
- Font cap raised from 13 → 22 px, floor 9 px; padX scales with font
  so an A3-corner placement comes out genuinely readable
- "Total" label sits in column 2 (over From) instead of overlapping
  the # column

Co-Authored-By: Claude Sonnet 4.7 <noreply@anthropic.com>
…er '--'

drawFlightPlanTable reads the module-global `aircraft` to compute
per-leg fuel. Before, that was only seeded inside showFlightPlan's
syncAircraftUI(). A user who opened the export modal straight from
the toolbar (without ever touching the Flight Plan) hit the fuel
calculation with aircraft = null and every cell rendered as '--'.

loadAircraft() now applies AIRCRAFT_DEFAULTS = { gph: 8, taxiGal: 1.1 }
whenever localStorage has nothing valid, and is called eagerly at
module parse time. The Flight Plan modal still overrides via the user
inputs as before.

Co-Authored-By: Claude Sonnet 4.7 <noreply@anthropic.com>
rowH = h / numRows let the placeholder height dictate spacing — a tall
placeholder spaced rows out, leaving lots of empty padding between
each line. Now: compute font first (~70 % of ideal row), then
rowH = min(ideal, ceil(font × 1.35)). Vertical slack lives as
whitespace below the table, not between rows.

Outer border + grid lines now use `tableH = rowH × numRows` instead
of the placeholder height so they hug the actual content.

Co-Authored-By: Claude Sonnet 4.7 <noreply@anthropic.com>
…lder

After the rowH cap, the actual rendered table is usually shorter than
the placeholder rect. drawFlightPlanTable always drew at the rect's
top-left, so a BR placement put the table mid-right instead of in the
true bottom-right corner.

Add an alignment param: drawFlightPlanTable(ctx, x, y, w, h, align)
where align ∈ tl | tr | bl | br | center. After computing totalW and
tableH, shift (x, y) inside the host rect to the chosen corner.

planPlacementAlign module-level var stores the user's pick from the
export modal (corner picks → tl/tr/bl/br, None/Custom → center).
exportPNG passes it through.

Co-Authored-By: Claude Sonnet 4.7 <noreply@anthropic.com>
CodeQL flagged swapHeaders as unused — it had been the pin-mode
header swapper and lost its sole caller when the pin code went.
Removing it pulls the supporting fpThCells / rfpThCells arrays
out of both table builders too.

Co-Authored-By: Claude Sonnet 4.7 <noreply@anthropic.com>
Change page.goto('/?lang=en') to page.goto('?lang=en') in all test
files so they resolve relative to the baseURL path instead of the
domain root. Fixes e2e-deployed tests hitting the production site
instead of the PR preview.
When EXPECTED_SHA env var is set (e2e-deployed workflow), each test
verifies the deployed core.js SHA matches after the test runs.
Catches cases where page.goto resolves to a different deployment
than the intended preview.
tintFill only accepts one argument (hex). The second argument was an
unused alpha override that should be removed. Notes always use the
global yellowAlpha opacity.
Replaces the 6 placement buttons (None/TL/TR/BL/BR/Custom) in the
Export PNG modal with a drag zone that shows a scaled preview of the
page frame. Clicking the zone places a mini flight-plan table at the
clicked position; dragging moves it. A "× Remove" button clears it.

The mini preview renders actual leg data (from/to/hdg/dist/spd/alt/time)
so the user sees the real table layout inside the zone.

On export, planWysiwygPos {xPct,yPct} is converted to canvas pixel
coordinates: fpx = xPct * frame.w * scale, fpy = yPct * frame.h * scale.
Table width = 45% of frame width; height = 70% (drawFlightPlanTable
auto-clips to actual row count).

Zone is disabled when no A3/A4 page frame is active (shows hint).
Drag listeners are cleaned up on modal close.

Updated export-png-options tests for new interface.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions github-actions Bot marked this pull request as draft May 27, 2026 09:05
@msupino msupino changed the base branch from dev-planPin-v2 to dev May 27, 2026 10:30
@github-actions

github-actions Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

🚀 Preview deployed

Open PR preview →

https://msupino.github.io/NavigationApp/branch/wysiwyg-flight-plan/

Commit: 3b4574e

Comment thread docs/io.js Fixed
…ort, function or class'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Add i18n strings, instructional subtitle, styled clear control with id,
improved preview zone (max-height, paper dashed frame, mini-table copy
from fpHeadersShort). Only attach drag listeners when a page frame exists;
guard mouseup handler. Update export e2e to use #export-wysi-remove.

Co-authored-by: Cursor <cursoragent@cursor.com>
Resolve core.js / he/strings.js conflicts by keeping dev’s tbIssues +
keyboard-shortcuts i18n alongside the WYSIWYG export strings from #378.

Co-authored-by: Cursor <cursoragent@cursor.com>
# Conflicts:
#	docs/core.js
#	docs/he/strings.js
#	docs/io.js
#	tests/flight-plan.spec.js
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.

2 participants