diff --git a/js/map.js b/js/map.js index eaf88b3..7c1a9ab 100644 --- a/js/map.js +++ b/js/map.js @@ -109,7 +109,7 @@ function _patchStyleWater(styleObj) { // Colors pre-compensated for canvas filter brightness(1.8) contrast(0.9). if (_mapStyle === 'dark') { // Darker water for Dark Map - const waterColor = '#131619'; + const waterColor = '#17212b'; for (const layer of styleObj.layers) { if (!layer.paint) layer.paint = {}; if (layer.type === 'fill' && /^water/.test(layer.id)) { @@ -357,10 +357,17 @@ function applyExtraLayers() { function apply3DBuildings() { if (!map.getSource || !map.getSource('openmaptiles')) return; - const shouldShow = buildings3DVisible && !['satellite', 'satellite3d', 'terrain3d', 'globe'].includes(_mapStyle); - if (shouldShow && !map.getLayer('matrix-buildings-3d')) { - // Insert below the first symbol layer so road/POI labels render on top of buildings - const firstSymbol = map.getStyle()?.layers?.find(l => l.type === 'symbol'); + const noBuildings = ['satellite', 'satellite3d', 'terrain3d', 'globe']; + const shouldShow = buildings3DVisible && !noBuildings.includes(_mapStyle); + // Toggle the style's native fill-extrusion layers (OpenFreeMap styles include 3D buildings) + const styleLayers = map.getStyle()?.layers || []; + const nativeExtrusions = styleLayers.filter(l => l.type === 'fill-extrusion' && l.id !== 'matrix-buildings-3d'); + if (nativeExtrusions.length) { + const vis = shouldShow ? 'visible' : 'none'; + nativeExtrusions.forEach(l => map.setLayoutProperty(l.id, 'visibility', vis)); + } else if (shouldShow && !map.getLayer('matrix-buildings-3d')) { + // Style lacks native 3D buildings — add custom layer (e.g. dark mode) + const firstSymbol = styleLayers.find(l => l.type === 'symbol'); map.addLayer({ id: 'matrix-buildings-3d', type: 'fill-extrusion', diff --git a/tests/helpers/test-setup.js b/tests/helpers/test-setup.js index 516a240..78ba982 100644 --- a/tests/helpers/test-setup.js +++ b/tests/helpers/test-setup.js @@ -21,7 +21,7 @@ async function setupApp(page) { return !!document.querySelector('#map canvas') && typeof db !== 'undefined' && db !== null; } catch { return false; } }, - { timeout: 20000 } + { timeout: 45000 } ); } @@ -40,7 +40,7 @@ async function uploadTestPhotos(page, fileNames) { const toast = document.getElementById('toast'); return toast && toast.classList.contains('show') && toast.textContent.includes('Added'); }, - { timeout: 20000 } + { timeout: 45000 } ); // Expand all collapsed year groups so photo cards render in the DOM // (the app uses virtual scrolling and year groups start collapsed) diff --git a/tests/playwright.config.js b/tests/playwright.config.js index cca9654..f1496e3 100644 --- a/tests/playwright.config.js +++ b/tests/playwright.config.js @@ -11,7 +11,6 @@ module.exports = defineConfig({ baseURL: 'http://localhost:8765', headless: true, viewport: { width: 1280, height: 800 }, - actionTimeout: 30000, serviceWorkers: 'block', }, projects: [ diff --git a/tests/specs/settings-export-import.spec.js b/tests/specs/settings-export-import.spec.js index c5305bc..e42880e 100644 --- a/tests/specs/settings-export-import.spec.js +++ b/tests/specs/settings-export-import.spec.js @@ -93,4 +93,25 @@ test.describe('Settings & Export/Import', () => { expect(imported).toBe(1); await expect(page.locator('#stat-photos')).toHaveText('1'); }); + + test('empty map cache clears tiles and shows toast', async ({ page }) => { + // Pre-create a fake tile file so there's something to delete + await page.request.post( + '/api/tiles/cache?url=https://tiles.openfreemap.org/planet/test/0/0/0.pbf', + { data: Buffer.from('fake tile'), headers: { 'Content-Type': 'application/octet-stream' } } + ); + + await page.locator('.settings-btn').click(); + await expect(page.locator('#settings-dropdown')).toHaveClass(/open/); + + // Override the beforeEach dismiss handler to accept the confirmation dialog + page.removeAllListeners('dialog'); + page.on('dialog', d => d.accept()); + + await page.locator('.settings-item', { hasText: 'Empty Map Cache' }).click(); + + // Success toast confirms tiles were removed + await expect(page.locator('#toast')).toContainText('Map cache cleared', { timeout: 5000 }); + await expect(page.locator('#toast')).toHaveClass(/success/); + }); });