3.1.0.1
Why it feels now updates on play
This commit is contained in:
+18
-5
@@ -69,6 +69,12 @@ function interpolateRowAt(rows, t) {
|
||||
elev: L(lo.elev, hi.elev),
|
||||
glob: L(lo.glob, hi.glob),
|
||||
utciAdj: L(lo.utciAdj, hi.utciAdj),
|
||||
// Felt-temp inputs — interpolated so the "Why It Feels" panel breakdown
|
||||
// stays smooth and consistent with the (interpolated) utciAdj category.
|
||||
Ta: L(lo.Ta, hi.Ta),
|
||||
Tmrt: L(lo.Tmrt, hi.Tmrt),
|
||||
va: L(lo.va, hi.va),
|
||||
eh: L(lo.eh, hi.eh),
|
||||
cc: L(lo.cc, hi.cc),
|
||||
ccLow: L(lo.ccLow, hi.ccLow),
|
||||
ccMid: L(lo.ccMid, hi.ccMid),
|
||||
@@ -413,8 +419,8 @@ export function UTCIForecast() {
|
||||
const airTempRgbVeryStrong = (t) => airTempRgb(t, 0.25);
|
||||
|
||||
// ─── 3b. PANEL COMPUTATIONS ──────────────────────────────────────────
|
||||
// Derived from currentRow and the active day - no side effects.
|
||||
const whyFeelsLike = computeWhyFeelsLike(currentRow ?? null, UTCI_ENVIRONMENTS[utciEnv]);
|
||||
// whyFeelsLike is derived below, after the playback rows are resolved, so
|
||||
// the panel can track the simulated instant during play/scrub (see panelRow).
|
||||
|
||||
// Interpolated row at the precise current instant — used for the scope
|
||||
// display even outside playback so there's no jump when play is pressed.
|
||||
@@ -432,6 +438,13 @@ export function UTCIForecast() {
|
||||
: (liveElev ?? currentRow?.elev ?? 0);
|
||||
const scopeDt = simRow ? simRow.dt : now;
|
||||
const scopeCat = scopeRow ? utciCategory(scopeRow.utciAdj) : currentCat;
|
||||
// "Why It Feels" panel always mirrors the scope dial: the simulated instant
|
||||
// during play/scrub, and the interpolated "now" row (scopeRow → nowRow) when
|
||||
// stopped. Sharing scopeRow/scopeCat guarantees the panel's thermal label can
|
||||
// never disagree with the dial's reticle.
|
||||
const panelRow = scopeRow;
|
||||
const panelCat = scopeCat;
|
||||
const whyFeelsLike = computeWhyFeelsLike(panelRow ?? null, UTCI_ENVIRONMENTS[utciEnv]);
|
||||
// Synthesize a storm overlay (lightning) when the simulated hour is wet;
|
||||
// outside playback keep the real active event.
|
||||
const scopeEvent = simRow ? ((simRow.precip ?? 0) >= 4 ? { id: 'storm' } : null) : lensEvent;
|
||||
@@ -751,7 +764,7 @@ export function UTCIForecast() {
|
||||
</div>
|
||||
|
||||
<div class="header-right">
|
||||
${forecast && currentRow && whyFeelsLike && html`
|
||||
${forecast && panelRow && whyFeelsLike && html`
|
||||
<div class="insight-panel insight-panel--why">
|
||||
<div class="insight-env-footer" data-env=${utciEnv}>
|
||||
<span class="insight-env-footer-label">Solar model</span>
|
||||
@@ -769,11 +782,11 @@ export function UTCIForecast() {
|
||||
</div>
|
||||
<div class="insight-panel-title">
|
||||
Why It Feels
|
||||
${currentCat && html`<span class="insight-thermal-cat" style=${{ background: currentCat.bg, color: currentCat.fg }}>${currentCat.label}</span>`}
|
||||
${panelCat && html`<span class="insight-thermal-cat" style=${{ background: panelCat.bg, color: panelCat.fg }}>${panelCat.label}</span>`}
|
||||
</div>
|
||||
${(() => {
|
||||
const _wflItems = [
|
||||
{ label: 'Air temperature', icon: '🌡', value: currentRow.Ta, isBase: true },
|
||||
{ label: 'Air temperature', icon: '🌡', value: panelRow.Ta, isBase: true },
|
||||
{ label: 'Sun and sky', icon: '☀', value: whyFeelsLike.sunAndSky },
|
||||
{ label: 'Wind', icon: '🌬', value: whyFeelsLike.wind },
|
||||
{ label: 'Humidity', icon: '💧', value: whyFeelsLike.humidity },
|
||||
|
||||
@@ -484,15 +484,27 @@ export function DayTabs({
|
||||
title: 'Office is part of SunScope Extra',
|
||||
detail: 'Extra adds the Office profile with solar gain, managed indoor temperature, humidity, air quality, and rain probability — useful for commute planning and building comfort.',
|
||||
},
|
||||
'variant:driver': {
|
||||
title: 'Driver / Trucker is part of SunScope Extra',
|
||||
detail: 'Extra adds the Driver / Trucker profile with vehicle interior temperature, UV, wind speed and direction, rain probability, and visibility — the conditions that matter for long hours on the road.',
|
||||
},
|
||||
'export': {
|
||||
title: 'Export day data is part of SunScope Extra',
|
||||
detail: 'Extra lets you download a full hourly spreadsheet for any day — all 41 columns including felt temperature, UV, soil, wind, and air quality, styled and ready to use in Excel or LibreOffice.',
|
||||
},
|
||||
};
|
||||
const promptCopy = extraPromptCopy[proPromptSource] || {
|
||||
// Day-tab locks get the day-specific heading; any other locked feature
|
||||
// without its own entry above falls back to a feature-agnostic message.
|
||||
const fallbackCopy = proPromptSource === 'day'
|
||||
? {
|
||||
title: `${dayName}'s forecast is part of SunScope Extra`,
|
||||
detail: 'Extra unlocks the full 14-day forecast, customisable columns, specialist profiles, and an ad-free view.',
|
||||
}
|
||||
: {
|
||||
title: 'This is part of SunScope Extra',
|
||||
detail: 'Extra unlocks the full 14-day forecast, customisable columns, specialist profiles, and an ad-free view.',
|
||||
};
|
||||
const promptCopy = extraPromptCopy[proPromptSource] || fallbackCopy;
|
||||
return html`
|
||||
<${SubscribeModal}
|
||||
title=${promptCopy.title}
|
||||
|
||||
Reference in New Issue
Block a user