Skip to content

Commit d4e71a4

Browse files
authored
fix: loader and navigation and update v0.1.3-alpha changelog entries (#25)
* test: migrate LandingPageTests to BunitContext and Render. * chore: update changelog for v0.1.3-alpha release and fix various issues. * fix: guard MutationObserver write and pin release-drafter target-commitish. * chore: remove target-commitish from release-drafter config and ensure commitish is set in workflow.
1 parent 94036fa commit d4e71a4

9 files changed

Lines changed: 155 additions & 35 deletions

File tree

.github/workflows/release-drafter.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ jobs:
1919
- uses: release-drafter/release-drafter@v7
2020
with:
2121
config-name: release-drafter.yml
22+
commitish: main
2223
env:
2324
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,24 @@ All notable changes to **preflight.xml** are documented here. Format follows
1313
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
1414
<!-- internal:end -->
1515

16+
## v0.1.3-alpha
17+
18+
### Fixed
19+
20+
- "Open in Advanced" button on docs pages now works on GitHub Pages -
21+
the link no longer escapes the `/preflight.xml/` base path because
22+
of a stray leading slash in the href.
23+
- Loading-screen runway no longer renders fully drawn from the first
24+
frame in WebView2 / older Chromium - the trail now actually grows
25+
behind the plane as Blazor reports boot progress, instead of
26+
appearing pre-drawn.
27+
28+
### Changed
29+
30+
- Cosmetic polish on the loading screen - taller container with proper
31+
breathing room above and below the wave, so the plane's glow halo is
32+
no longer clipped at the top of tall waves or at the runway baseline.
33+
1634
## v0.1.2-alpha
1735

1836
### Added

CHANGELOG.uk.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,25 @@
1313
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
1414
<!-- internal:end -->
1515

16+
## Версія v0.1.3-alpha
17+
18+
### Виправлено
19+
20+
- Кнопка "Доналаштувати в Advanced" на сторінках документації тепер
21+
коректно працює на GitHub Pages - посилання більше не виходить за
22+
межі базового шляху `/preflight.xml/` через зайвий слеш на початку
23+
href.
24+
- Доріжка лоадера на старті більше не виглядає вже промальованою з
25+
першого кадру у WebView2 / старіших Chromium - шлейф тепер дійсно
26+
росте позаду літака за реальним прогресом завантаження Blazor,
27+
замість того щоб бути намальованим заздалегідь.
28+
29+
### Змінено
30+
31+
- Косметичні поправки на екрані завантаження - вищий контейнер з
32+
адекватним простором над і під хвилею, тож ореол літака більше не
33+
обрізається на піках хвиль чи на нижній лінії доріжки.
34+
1635
## Версія v0.1.2-alpha
1736

1837
### Додано

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
</PropertyGroup>
2828

2929
<PropertyGroup Label="Package">
30-
<VersionPrefix>0.1.2</VersionPrefix>
30+
<VersionPrefix>0.1.3</VersionPrefix>
3131
<VersionSuffix>alpha</VersionSuffix>
3232
<Version>$(VersionPrefix)-$(VersionSuffix)</Version>
3333
<PackageVersion>$(Version)</PackageVersion>

Preflight.slnx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,31 @@
2020
<File Path="justfile" />
2121
</Folder>
2222

23-
<!-- Project docs -->
23+
<!-- Project docs (top-level + docs/) -->
2424
<Folder Name="/docs/">
2525
<File Path="README.md" />
2626
<File Path="AGENTS.md" />
2727
<File Path="CONTRIBUTING.md" />
2828
<File Path="SECURITY.md" />
2929
<File Path="NOTICE" />
30+
<File Path="CHANGELOG.md" />
31+
<File Path="CHANGELOG.uk.md" />
3032
<File Path="docs/README.md" />
3133
<File Path="docs/architecture.md" />
3234
<File Path="docs/ci-cd.md" />
35+
<File Path="docs/changelog.md" />
36+
<File Path="docs/development.md" />
3337
<File Path="docs/publishing.md" />
3438
<File Path="docs/releasing.md" />
3539
<File Path="docs/upstream-sync.md" />
3640
</Folder>
3741

42+
<!-- Licenses & third-party attribution -->
43+
<Folder Name="/legal/">
44+
<File Path="LICENSE" />
45+
<File Path="LICENSES/schneegans-MIT.txt" />
46+
</Folder>
47+
3848
<!-- GitHub Actions & repo meta -->
3949
<Folder Name="/.github/">
4050
<File Path=".github/workflows/ci.yml" />

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<br>
88

99
<p>
10-
<a href="https://github.com/kYaRick/preflight.xml/releases"><img alt="Version" src="https://img.shields.io/static/v1?label=version&message=v0.1.2-alpha&color=0ea5e9"></a>
10+
<a href="https://github.com/kYaRick/preflight.xml/releases"><img alt="Version" src="https://img.shields.io/static/v1?label=version&message=v0.1.3-alpha&color=0ea5e9"></a>
1111
<a href="https://dotnet.microsoft.com/"><img alt=".NET 10" src="https://img.shields.io/badge/.NET-10-512BD4?logo=dotnet&logoColor=white"></a>
1212
<a href="https://learn.microsoft.com/aspnet/core/blazor/"><img alt="Blazor WASM" src="https://img.shields.io/badge/Blazor-WebAssembly-512BD4?logo=blazor&logoColor=white"></a>
1313
<a href="https://www.fluentui-blazor.net/"><img alt="Fluent UI" src="https://img.shields.io/badge/Fluent%20UI-Blazor-0078D4?logo=microsoft&logoColor=white"></a>
@@ -21,7 +21,7 @@
2121

2222
> [!WARNING]
2323
> **Pre-alpha.** The Blazor app is being scaffolded - APIs, UI and file
24-
> layout can change without notice until `v0.1.2`. Pin to a specific tag
24+
> layout can change without notice until `v0.1.3`. Pin to a specific tag
2525
> if you depend on it.
2626
2727
---

srcs/Preflight.App/Pages/Docs/DocsEntry.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ else
2525
<FluentAnchor Href="docs" Appearance="Appearance.Outline">← @L["Docs.BackToIndex"]</FluentAnchor>
2626
@if (IsKnownSection)
2727
{
28-
<FluentAnchor Href="@($"/advanced/{Slug}")" Appearance="Appearance.Outline">⚙️ @L[@"Docs.OpenInAdvanced"]</FluentAnchor>
28+
<FluentAnchor Href="@($"advanced/{Slug}")" Appearance="Appearance.Outline">⚙️ @L[@"Docs.OpenInAdvanced"]</FluentAnchor>
2929
}
3030
<FluentSpacer />
3131
<FluentAnchor Href="" Appearance="Appearance.Outline">← @L["Common.BackToHome"]</FluentAnchor>

srcs/Preflight.App/wwwroot/css/app.css

Lines changed: 56 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2283,9 +2283,16 @@ fluent-select {
22832283
loader's pre-transform width MUST stay at 25rem (= 400px) for the
22842284
plane to land on the runway. On narrow viewports we apply a uniform
22852285
transform: scale() instead of shrinking width - that keeps the
2286-
coordinate space intact while still fitting the screen. */
2286+
coordinate space intact while still fitting the screen.
2287+
2288+
Height bumped from 6.25rem → 8rem so the plane's 14px drop-shadow
2289+
halo has breathing room above the wave peak and below the trough -
2290+
the previous height clipped the glow on tall waves. overflow:visible
2291+
is explicit (defensive) so any descendant filter spill renders even
2292+
if a future layout adds a clipping ancestor. */
22872293
width: 25rem;
2288-
height: 6.25rem;
2294+
height: 8rem;
2295+
overflow: visible;
22892296
z-index: 2;
22902297
/* Uniform downscale so the 400px SVG fits any viewport. The 2rem
22912298
safety margin on each side keeps the loader off the screen edges
@@ -2298,7 +2305,10 @@ fluent-select {
22982305

22992306
.runway-wave {
23002307
position: absolute;
2301-
top: 1.25rem;
2308+
/* Centered vertically inside the 8rem loader (8 - 3.75) / 2 ≈ 2.125rem,
2309+
which leaves ~1rem above the wave peaks for the plane's drop-shadow
2310+
halo and ~1rem below the troughs before the status text. */
2311+
top: 2.125rem;
23022312
left: 0;
23032313
width: 25rem;
23042314
height: 3.75rem;
@@ -2326,43 +2336,52 @@ fluent-select {
23262336
A horizontal mask gradient fades the trail's tail so the oldest part of
23272337
the flight path dissolves behind the plane - visually separates the
23282338
glowing plane from the line, which were blending into one violet smear. */
2339+
/* Register --pf-trail-progress as a typed <number> so it interpolates
2340+
smoothly under transitions. Without @property, custom properties are
2341+
opaque strings to CSS - the consumer property still transitions, but
2342+
var-driven calc() results sometimes pin to discrete computed values
2343+
in WebView2 / older Chromium, which is exactly the asymmetry that
2344+
made the trail "snap" while the plane glided behind it. */
2345+
@property --pf-trail-progress {
2346+
syntax: "<number>";
2347+
inherits: true;
2348+
initial-value: 0;
2349+
}
2350+
23292351
/* Honest deterministic fill: the runway draws itself in lockstep with
23302352
ACTUAL Blazor boot progress, not a hardcoded 2.4s timeline.
23312353
2332-
Blazor WebAssembly auto-publishes its load progress to two CSS custom
2354+
Blazor WebAssembly publishes its load progress to two CSS custom
23332355
properties on <html>:
23342356
--blazor-load-percentage - e.g. "47%" (length-percentage)
23352357
--blazor-load-percentage-text - e.g. "47%" (string for content:)
2336-
The status text below already consumes the second one. Here we wire
2337-
the trail fill (and the plane's offset-distance) to the first so the
2338-
visual matches reality.
2339-
2340-
Math: pathLength="100" means dash values are interpreted as percent
2341-
of declared path length. A single dash of 100% covers the whole path;
2342-
stroke-dashoffset 100% pushes it fully off, 0% draws it fully. As
2343-
Blazor reports progress 0 → 100%, dashoffset moves 100% → 0%. The
2344-
transition smooths Blazor's chunky discrete bumps into a fluid bar. */
2358+
The status text below consumes the second one. The trail fill below
2359+
uses --pf-trail-progress (unitless 0..100), which a small JS bridge
2360+
in index.html mirrors from --blazor-load-percentage in the SAME
2361+
frame Blazor writes it (MutationObserver, not polled).
2362+
2363+
The bridge ALSO pins --pf-trail-length-px to the path's real total
2364+
length (~416px). We then drive stroke-dasharray as an ABSOLUTE pixel
2365+
length (`progress/100 * length`) instead of relying on the path's
2366+
pathLength="100" attribute to rescale unitless dash values - because
2367+
Chromium / WebView2 does not apply pathLength scaling to length-
2368+
typed dash values produced by var()/calc(). With "30px 100px" on a
2369+
416px curve the pattern repeats four times (visible drawn segments
2370+
at 0-30, 130-160, 260-290, 390-416), which is exactly the "line ahead
2371+
of the plane" symptom. Hard pixel math sidesteps the bug. */
23452372
.runway-trail {
23462373
stroke: url(#runwayGradient);
23472374
stroke-width: 2;
23482375
stroke-linecap: round;
2349-
/* Progressive reveal MUST be in path-length space so the trail tip
2350-
lands exactly under the plane. The plane uses
2351-
offset-distance: var(--blazor-load-percentage)
2352-
which is path-length-relative. Mixing in a horizontal-pixel mask
2353-
for the reveal desyncs them on a wavy path (path length > box
2354-
width, so x-progress runs ahead of path-progress) - this caused
2355-
the previous bug where the line drew first and the plane chased
2356-
it. The path declares pathLength="100", so unitless dash values
2357-
are percent-of-path-length. The /1% trick collapses the percent
2358-
unit (e.g. 60% / 1% = 60) so we can pass a path-relative offset
2359-
where SVG would normally treat % as viewport-diagonal. */
2360-
stroke-dasharray: 100;
2361-
stroke-dashoffset: calc(100 - var(--blazor-load-percentage, 0%) / 1%);
2376+
/* ON segment = progress% of the curve's actual length. The OFF
2377+
segment is set far longer than the path so the dash pattern can
2378+
never wrap onto a second visible repetition. */
2379+
stroke-dasharray: calc(var(--pf-trail-progress, 0) / 100 * var(--pf-trail-length-px, 416px)) 9999px;
2380+
stroke-dashoffset: 0;
23622381
/* Smooth fade-in at the very start of the runway. This mask is
23632382
STATIC (not progress-dependent) - it always fades the leftmost
23642383
portion of the SVG box so the trail never starts abruptly at
2365-
x=0. Combined with the dashoffset reveal above, the result is:
2384+
x=0. Combined with the dasharray reveal above, the result is:
23662385
trail grows from start to plane, leftmost ~12% softened. */
23672386
-webkit-mask-image: linear-gradient(to right,
23682387
rgba(0, 0, 0, 0) 0%,
@@ -2374,7 +2393,11 @@ fluent-select {
23742393
rgba(0, 0, 0, 1) 100%);
23752394
filter: drop-shadow(0 0 4px var(--pf-accent));
23762395
opacity: 0.9;
2377-
transition: stroke-dashoffset 0.35s cubic-bezier(0.4, 0, 0.2, 1);
2396+
/* Match the plane's offset-distance transition so the trail tip and
2397+
the plane glide together (both 0.35s, same easing). Transitioning
2398+
--pf-trail-progress (typed as <number> via @property above) makes
2399+
any consumer of var(--pf-trail-progress) interpolate smoothly. */
2400+
transition: --pf-trail-progress 0.35s cubic-bezier(0.4, 0, 0.2, 1);
23782401
}
23792402

23802403
/* Plane follows the EXACT same path the SVG drew. Both use the 400x60
@@ -2383,11 +2406,15 @@ fluent-select {
23832406
Inline SVG with gradient fill - bulletproof visibility across themes. */
23842407
.plane {
23852408
position: absolute;
2386-
top: 1.25rem;
2409+
/* Match .runway-wave's top so offset-path coordinates stay aligned -
2410+
the plane's offset-path uses the same 0..400 / 0..60 space as the
2411+
wave SVG, so both must anchor at the same loader-relative y. */
2412+
top: 2.125rem;
23872413
left: 0;
23882414
width: 1.75rem;
23892415
height: 1.75rem;
23902416
display: block;
2417+
overflow: visible;
23912418
pointer-events: none;
23922419

23932420
offset-path: path("M 0 30 Q 50 5, 100 30 T 200 30 T 300 30 T 400 30");

srcs/Preflight.App/wwwroot/index.html

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@
137137
</linearGradient>
138138
</defs>
139139
<path class="runway-track" d="M 0 30 Q 50 5, 100 30 T 200 30 T 300 30 T 400 30" />
140-
<path class="runway-trail" d="M 0 30 Q 50 5, 100 30 T 200 30 T 300 30 T 400 30" pathLength="100" />
140+
<path class="runway-trail" d="M 0 30 Q 50 5, 100 30 T 200 30 T 300 30 T 400 30" />
141141
</svg>
142142
<!-- Inline SVG airplane, gradient-filled. Always visible, no
143143
background-clip:text quirks across browsers/themes. -->
@@ -198,18 +198,63 @@
198198
// 2.4s wait stacked on top of the splash.
199199
const MIN_DISPLAY_MS = PF_IS_DESKTOP ? 0 : 2400;
200200
const started = Date.now();
201+
const html = document.documentElement;
201202

202203
const notifyHost = () => {
203204
try { window.chrome?.webview?.postMessage('preflight:ready'); }
204205
catch { /* not in WebView2 - ignore */ }
205206
};
206207

208+
// Bridge Blazor's "47%" string → unitless 47 in --pf-trail-progress.
209+
// Also pin --pf-trail-length-px to the path's actual computed length
210+
// (~416 user units for the wave curve). The trail dash-array uses
211+
// absolute pixels rather than relying on SVG `pathLength` scaling,
212+
// because Chromium / WebView2 does NOT apply pathLength to length-
213+
// typed dash values that were computed via CSS calc() / var() - it
214+
// treats them as raw px. With dasharray "30px 100px" on a 416px
215+
// path the pattern WAS repeating (drawn at 0-30, 130-160, 260-290,
216+
// 390-416), which is exactly the "line ahead of the plane" the
217+
// user reported. Computing dasharray from the real path length
218+
// sidesteps the issue entirely.
219+
//
220+
// Observation-driven, not polled: a MutationObserver watches <html>'s
221+
// style attribute and mirrors --blazor-load-percentage to
222+
// --pf-trail-progress in the SAME frame Blazor writes it. Polling at
223+
// 120ms (the previous approach) made the plane and trail start their
224+
// CSS transitions out of phase.
225+
const trailPath = document.querySelector('.runway-trail');
226+
if (trailPath) {
227+
try {
228+
const len = trailPath.getTotalLength();
229+
if (len > 0) html.style.setProperty('--pf-trail-length-px', `${len}px`);
230+
} catch { /* getTotalLength can throw on detached / pre-layout SVG */ }
231+
}
232+
let _lastTrailProgress = null;
233+
const syncTrail = () => {
234+
const raw = html.style.getPropertyValue('--blazor-load-percentage')
235+
|| getComputedStyle(html).getPropertyValue('--blazor-load-percentage');
236+
if (!raw) return;
237+
const num = parseFloat(raw);
238+
if (Number.isNaN(num)) return;
239+
const next = String(num);
240+
if (next === _lastTrailProgress) return;
241+
_lastTrailProgress = next;
242+
html.style.setProperty('--pf-trail-progress', next);
243+
};
244+
syncTrail();
245+
const trailObserver = new MutationObserver(syncTrail);
246+
trailObserver.observe(html, { attributes: true, attributeFilter: ['style'] });
247+
207248
const handle = setInterval(() => {
208249
const blazorReady = !!document.querySelector('.layout');
209250
const isNotFound = !!document.querySelector('.pf-404');
210251
const minElapsed = Date.now() - started >= MIN_DISPLAY_MS;
211252
if (blazorReady && (minElapsed || isNotFound)) {
212253
clearInterval(handle);
254+
trailObserver.disconnect();
255+
// Pin trail at 100% before fade-out so the runway lands on
256+
// the right-hand crest instead of freezing mid-flight.
257+
html.style.setProperty('--pf-trail-progress', '100');
213258
overlay.classList.add('is-done');
214259
// Trigger the first page-enter animation AFTER the loader
215260
// starts fading. Without this, the page-enter would run

0 commit comments

Comments
 (0)