mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
fix(street-level): fit the whole photo on phones
At phone width the right rail is the band between mid-screen and the credit line, so a 16:10 viewer plus its bar and caption was cut off. Below 720 px the viewer's height is derived from that band (clamped 110-320 px); floating and expanded viewers reset to auto height. The QA harness checks the photo and caption fit at 390x844, and CURRENT-STATE documents the docking rules and phone sizing. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
6207e4144e
commit
e6c2c812f9
4 files changed
+91
-2
No files matched your search
@@ -2796,8 +2796,12 @@ the settings follow. SINCE is a stepped range input (any date, 10, 5, 3, 2 and
|
|||||||
1 years, 6, 3 and 1 months) whose readout names the cut-off date. The panel is
|
1 years, 6, 3 and 1 months) whose readout names the cut-off date. The panel is
|
||||||
portable (`street-level-panel` spec in `PanelPositionControls`, minimum
|
portable (`street-level-panel` spec in `PanelPositionControls`, minimum
|
||||||
320 × 280, `dockOnCollapse`): in a resized window the viewer takes the spare
|
320 × 280, `dockOnCollapse`): in a resized window the viewer takes the spare
|
||||||
height and only `.sl-settings` scrolls, and collapsing the window or SHRINK
|
height and only `.sl-settings` scrolls, and a user's collapse, a header
|
||||||
after EXPAND docks it at its default size.
|
double-click or SHRINK after EXPAND docks it at its default size (cockpit
|
||||||
|
entry, restores and the Cyber accordion never dock a floating window). At
|
||||||
|
phone width (≤720 px) the rail is the band between mid-screen and the credit
|
||||||
|
line, so the viewer's height is derived from that band instead of 16:10 and
|
||||||
|
the whole photo and caption fit without scrolling.
|
||||||
|
|
||||||
Street-level providers implement the contract documented in
|
Street-level providers implement the contract documented in
|
||||||
`src/layers/streetLevel/registry.js`: a definition (`id`, `name`, `label`,
|
`src/layers/streetLevel/registry.js`: a definition (`id`, `name`, `label`,
|
||||||
|
|||||||
@@ -621,6 +621,63 @@ async function main() {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
await step(
|
||||||
|
'on a phone the whole photo fits in the docked panel',
|
||||||
|
async () => {
|
||||||
|
await page.setViewport({
|
||||||
|
width: 390,
|
||||||
|
height: 844,
|
||||||
|
isMobile: true,
|
||||||
|
hasTouch: true,
|
||||||
|
});
|
||||||
|
await sleep(800);
|
||||||
|
if (
|
||||||
|
await page.$eval('#street-level-panel', (node) =>
|
||||||
|
node.classList.contains('collapsed'),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
await page.click(
|
||||||
|
'.panel-collapse-btn[data-collapse-target="street-level-panel"]',
|
||||||
|
);
|
||||||
|
await page.evaluate((id) => {
|
||||||
|
void window.__godsEyeView.dataManager.layers
|
||||||
|
.get('street-level')
|
||||||
|
.module.openImage('mapillary', id);
|
||||||
|
}, firstImageId);
|
||||||
|
await page.waitForFunction(
|
||||||
|
() => {
|
||||||
|
const s = window.__godsEyeView.dataManager.layers
|
||||||
|
.get('street-level')
|
||||||
|
.module.getUIState().street;
|
||||||
|
return (s.imageId && !s.loading) || s.error;
|
||||||
|
},
|
||||||
|
{ timeout: 90_000 },
|
||||||
|
);
|
||||||
|
await sleep(600);
|
||||||
|
const fit = await page.evaluate(() => {
|
||||||
|
const inner = document
|
||||||
|
.querySelector('.street-level-panel-inner')
|
||||||
|
.getBoundingClientRect();
|
||||||
|
const meta = document
|
||||||
|
.getElementById('sl-image-meta')
|
||||||
|
.getBoundingClientRect();
|
||||||
|
const viewer = document
|
||||||
|
.getElementById('sl-viewer')
|
||||||
|
.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
cut: Math.round(meta.bottom - inner.bottom),
|
||||||
|
top: Math.round(viewer.top - inner.top),
|
||||||
|
height: Math.round(viewer.height),
|
||||||
|
overflowX: document.documentElement.scrollWidth > innerWidth,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
assert.ok(fit.cut <= 1, `photo and caption fit (${fit.cut}px cut)`);
|
||||||
|
assert.ok(fit.height >= 100, `viewer stays usable (${fit.height}px)`);
|
||||||
|
assert.equal(fit.overflowX, false, 'no sideways scroll');
|
||||||
|
await page.setViewport(VIEWPORTS[0]);
|
||||||
|
await sleep(600);
|
||||||
|
},
|
||||||
|
);
|
||||||
await step('no page errors', () => {
|
await step('no page errors', () => {
|
||||||
assert.deepEqual(errors, []);
|
assert.deepEqual(errors, []);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -122,6 +122,19 @@ test('labels say what the buttons do', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('on phones the viewer is sized from the rail band, not its aspect ratio', () => {
|
||||||
|
assert.match(
|
||||||
|
panelCss,
|
||||||
|
/@media \(max-width: 720px\) \{\s*\.sl-viewer \{[^}]*height: clamp\(/,
|
||||||
|
);
|
||||||
|
// Floating and expanded viewers must not inherit the phone height.
|
||||||
|
for (const selector of [
|
||||||
|
".panel-floating\\[style\\*='height'\\] \\.sl-viewer",
|
||||||
|
'\\.sl-viewer-wrap-expanded \\.sl-viewer',
|
||||||
|
])
|
||||||
|
assert.match(panelCss, new RegExp(`${selector} \\{[^}]*height: auto`));
|
||||||
|
});
|
||||||
|
|
||||||
test('the viewer comes first and the panel is a portable, resizable window', () => {
|
test('the viewer comes first and the panel is a portable, resizable window', () => {
|
||||||
const controlsBlock = html.slice(html.indexOf('<fieldset id="sl-controls"'));
|
const controlsBlock = html.slice(html.indexOf('<fieldset id="sl-controls"'));
|
||||||
assert.ok(
|
assert.ok(
|
||||||
|
|||||||
@@ -461,6 +461,7 @@ button.sl-status:focus-visible {
|
|||||||
|
|
||||||
.panel-floating[style*='height'] .sl-viewer {
|
.panel-floating[style*='height'] .sl-viewer {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
height: auto;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
aspect-ratio: auto;
|
aspect-ratio: auto;
|
||||||
}
|
}
|
||||||
@@ -497,6 +498,7 @@ button.sl-status:focus-visible {
|
|||||||
|
|
||||||
.sl-viewer-wrap-expanded .sl-viewer {
|
.sl-viewer-wrap-expanded .sl-viewer {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
height: auto;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
aspect-ratio: auto;
|
aspect-ratio: auto;
|
||||||
}
|
}
|
||||||
@@ -541,3 +543,16 @@ button.sl-status:focus-visible {
|
|||||||
min-height: 150px;
|
min-height: 150px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Phones ──────────────────────────────────────────────────────────────── */
|
||||||
|
/* At this width the right rail is the band between mid-screen and the credit
|
||||||
|
line (responsive.css: top 50vh + 8px, bottom 2vh + 7.5rem). Size the photo
|
||||||
|
from that band, less the panel's header, tool bar and caption (~150px), so
|
||||||
|
the whole image shows without scrolling; EXPAND still gives full screen. */
|
||||||
|
@media (max-width: 720px) {
|
||||||
|
.sl-viewer {
|
||||||
|
aspect-ratio: auto;
|
||||||
|
height: clamp(110px, calc(48vh - 8px - 7.5rem - 150px), 320px);
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user