fix: re-sync globe map on fullscreen transitions (#1510)

* fix: re-sync globe map on fullscreen transitions

* fix: call resize() instead of render() and anchor test regex

resize() propagates to MapLibre canvas resize in DeckGL mode,
fixing stale canvas dimensions after fullscreen transitions.
Anchor test regex to setupMapFullscreen to avoid matching the
wrong toggle block.

---------

Co-authored-by: Elie Habib <elie.habib@gmail.com>
This commit is contained in:
Frank
2026-03-14 07:11:11 -07:00
committed by GitHub
parent 945de7f0d0
commit 9d88aff739
2 changed files with 42 additions and 2 deletions

View File

@@ -361,6 +361,7 @@ export class EventHandlerManager implements AppModule {
this.boundFullscreenHandler = () => { this.boundFullscreenHandler = () => {
fullscreenBtn.textContent = document.fullscreenElement ? '\u26F6' : '\u26F6'; fullscreenBtn.textContent = document.fullscreenElement ? '\u26F6' : '\u26F6';
fullscreenBtn.classList.toggle('active', !!document.fullscreenElement); fullscreenBtn.classList.toggle('active', !!document.fullscreenElement);
this.syncMapAfterLayoutChange();
}; };
document.addEventListener('fullscreenchange', this.boundFullscreenHandler); document.addEventListener('fullscreenchange', this.boundFullscreenHandler);
} }
@@ -733,6 +734,16 @@ export class EventHandlerManager implements AppModule {
}; };
} }
private syncMapAfterLayoutChange(delayMs = 320): void {
const sync = () => {
this.ctx.map?.setIsResizing(false);
this.ctx.map?.resize();
};
requestAnimationFrame(sync);
window.setTimeout(sync, delayMs);
}
private async exitFullscreenForNavigation(): Promise<void> { private async exitFullscreenForNavigation(): Promise<void> {
const fullscreenDocument = this.getFullscreenDocument(); const fullscreenDocument = this.getFullscreenDocument();
if (!fullscreenDocument.fullscreenElement && !fullscreenDocument.webkitFullscreenElement) return; if (!fullscreenDocument.fullscreenElement && !fullscreenDocument.webkitFullscreenElement) return;
@@ -1228,8 +1239,7 @@ export class EventHandlerManager implements AppModule {
document.body.classList.toggle('live-news-fullscreen-active', isFullscreen); document.body.classList.toggle('live-news-fullscreen-active', isFullscreen);
btn.innerHTML = isFullscreen ? shrinkSvg : expandSvg; btn.innerHTML = isFullscreen ? shrinkSvg : expandSvg;
btn.title = isFullscreen ? 'Exit fullscreen' : 'Fullscreen'; btn.title = isFullscreen ? 'Exit fullscreen' : 'Fullscreen';
// Notify map so globe (and deck.gl) can resize after CSS transition completes this.syncMapAfterLayoutChange();
setTimeout(() => this.ctx.map?.setIsResizing(false), 320);
}; };
btn.addEventListener('click', toggle); btn.addEventListener('click', toggle);

View File

@@ -0,0 +1,30 @@
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const root = resolve(__dirname, '..');
const src = readFileSync(join(root, 'src', 'app', 'event-handlers.ts'), 'utf-8');
describe('map fullscreen resize sync', () => {
it('defines a shared layout-sync helper that calls resize()', () => {
assert.match(src, /private syncMapAfterLayoutChange\(delayMs = 320\): void \{/);
assert.match(src, /this\.ctx\.map\?\.resize\(\)/);
assert.match(src, /requestAnimationFrame\(sync\)/);
assert.match(src, /window\.setTimeout\(sync, delayMs\)/);
});
it('re-syncs the map after browser fullscreen changes', () => {
const fullscreenHandlerBlock = src.match(/this\.boundFullscreenHandler = \(\) => \{([\s\S]*?)\n\s*\};/);
assert.ok(fullscreenHandlerBlock, 'Expected fullscreenchange handler block');
assert.match(fullscreenHandlerBlock[1], /this\.syncMapAfterLayoutChange\(\)/);
});
it('re-syncs the map after map-panel fullscreen toggles', () => {
const mapFullscreenBlock = src.match(/setupMapFullscreen[\s\S]*?const toggle = \(\) => \{([\s\S]*?)\n\s*\};/);
assert.ok(mapFullscreenBlock, 'Expected map fullscreen toggle block inside setupMapFullscreen');
assert.match(mapFullscreenBlock[1], /this\.syncMapAfterLayoutChange\(\)/);
});
});