added on_window_size_change event

This commit is contained in:
Jakob Pinterits
2024-05-28 17:37:12 +00:00
parent 93354c60f3
commit a2f5207d1b
14 changed files with 157 additions and 70 deletions
+17 -10
View File
@@ -54,6 +54,20 @@ const SCROLL_BAR_SIZE_IN_PIXELS = getScrollBarWidthInPixels();
export let pixelsPerRem = 16;
export let scrollBarSize = SCROLL_BAR_SIZE_IN_PIXELS / pixelsPerRem;
let notifyBackendOfWindowSizeChange = eventRateLimiter(
(newWidth: number, newHeight: number) => {
try {
callRemoteMethodDiscardResponse('onWindowSizeChange', {
newWidth: newWidth,
newHeight: newHeight,
});
} catch (e) {
console.warn(`Couldn't notify backend of window resize: ${e}`);
}
},
250
);
function main(): void {
if (typeof globalThis.PING_PONG_INTERVAL_SECONDS !== 'number') {
console.error(
@@ -100,7 +114,7 @@ function main(): void {
// Listen for URL changes, so the session can switch page
window.addEventListener('popstate', (event: PopStateEvent) => {
console.log(
console.debug(
`popstate event triggered; new URL is ${window.location.href}`
);
@@ -115,7 +129,7 @@ function main(): void {
// ScrollTarget, but not both.
// FIXME: Find a way to tell whether only the url fragment changed
console.trace(`URL changed to ${window.location.href}`);
callRemoteMethodDiscardResponse('onUrlChange', {
newUrl: window.location.href.toString(),
});
@@ -124,14 +138,7 @@ function main(): void {
// Listen for resize events
window.addEventListener('resize', (event) => {
// Notify the backend
try {
callRemoteMethodDiscardResponse('onWindowResize', {
newWidth: window.innerWidth / pixelsPerRem,
newHeight: window.innerHeight / pixelsPerRem,
});
} catch (e) {
console.warn(`Couldn't notify backend of window resize: ${e}`);
}
notifyBackendOfWindowSizeChange(window.innerWidth, window.innerHeight);
// Re-layout, but only if a root component already exists
let rootElement = document.body.querySelector(
+1 -1
View File
@@ -473,7 +473,7 @@ export function updateComponentStates(
Math.abs(deltaState._size_![1] - component.state._size_[1]) > 1e-6;
if (width_changed || height_changed) {
console.log(
console.trace(
`Triggering re-layout because component #${id} changed size: ${component.state._size_} -> ${deltaState._size_}`
);
component.makeLayoutDirty();
+1 -1
View File
@@ -37,7 +37,7 @@ function withPlotly(callback: () => void): void {
}
// Otherwise fetch plotly and call the callback when it's done
console.log('Fetching plotly.js');
console.trace('Fetching plotly.js');
let script = document.createElement('script');
script.src = '/rio/asset/plotly.min.js';
-1
View File
@@ -126,7 +126,6 @@ export class SwitcherComponent extends ComponentBase {
this.previousChildRequestedWidth !== childRequestedWidth ||
this.previousChildRequestedHeight !== childRequestedHeight
) {
console.debug('Detected child size change, starting animation');
this.isDeterminingLayout = true;
this.previousChildRequestedWidth = childRequestedWidth;
this.previousChildRequestedHeight = childRequestedHeight;
+1 -1
View File
@@ -257,7 +257,7 @@ export async function applyIcon(
// No, load it from the server
if (promise === undefined) {
console.log(`Fetching icon ${iconName} from server`);
console.trace(`Fetching icon ${iconName} from server`);
promise = fetch(`/rio/icon/${iconName}`).then((response) =>
response.text()
-9
View File
@@ -88,9 +88,7 @@ export class DragHandler extends EventHandler {
}
private _onMouseDown(event: MouseEvent): void {
console.debug('Drag: mouse down');
let onStartResult = this.onStart(event);
console.debug('Drag: onStart result', onStartResult);
// It's easy to forget to return a boolean. Make sure to catch this
// mistake.
@@ -105,7 +103,6 @@ export class DragHandler extends EventHandler {
return;
}
console.debug('Drag: mouse down stop propagation');
event.stopPropagation();
window.addEventListener('mousemove', this.onMouseMove, true);
@@ -114,7 +111,6 @@ export class DragHandler extends EventHandler {
}
private _onMouseMove(event: MouseEvent): void {
console.debug('Drag: mouse move');
this.hasDragged = true;
event.stopPropagation();
@@ -122,9 +118,7 @@ export class DragHandler extends EventHandler {
}
private _onMouseUp(event: MouseEvent): void {
console.debug('Drag: mouse up');
if (this.hasDragged) {
console.debug('Preventing default due to drag');
event.stopPropagation();
}
@@ -137,10 +131,7 @@ export class DragHandler extends EventHandler {
// nonetheless be stopped to prevent the click from being handled by
// other handlers.
console.debug('Drag: click');
if (this.hasDragged) {
console.debug('Preventing default due to drag');
event.stopPropagation();
event.stopImmediatePropagation();
event.preventDefault();
+34
View File
@@ -0,0 +1,34 @@
/**
* Creates a rate-limited version of the given function. The function will be
* called at most once every `delay` milliseconds. It is also guaranteed to be
* called at least once with the final set of arguments passed to the original
* function.
*
* @param callback - The function to be called when the window resizes.
* @param delay - The delay in milliseconds between function calls.
* @returns A function that removes the event listener.
*/
function eventRateLimiter(
callback: (...args: any[]) => void,
delay: number
): (...args: any[]) => void {
let timeout: number | null = null;
let lastArgs: any[] = [];
// Create a closure over the state
return (...args: any[]) => {
// Store the arguments, so future calls can use them
lastArgs = args;
// If a timeout is already set, do nothing
if (timeout) {
return;
}
// Set a timeout to call the function
timeout = window.setTimeout(() => {
timeout = null;
callback(...lastArgs);
}, delay);
};
}
+2 -2
View File
@@ -174,7 +174,7 @@ function onMessage(event: MessageEvent<string>) {
// Print a copy of the message because some messages are modified in-place
// when they're processed
console.log('Received message: ', JSON.parse(event.data));
console.trace('Received message: ', JSON.parse(event.data));
// Push it into the queue, to be processed as soon as the previous message
// has been processed
@@ -234,7 +234,7 @@ export function sendMessageOverWebsocket(message: object) {
return;
}
console.log('Sending message: ', message);
console.trace('Sending message: ', message);
websocket.send(JSON.stringify(message));
}
+1 -1
View File
@@ -44,7 +44,7 @@ export async function registerFont(
}
if (numFailures === 0) {
console.log(
console.trace(
`Successfully registered all ${numSuccesses} variations of font ${name}`
);
} else if (numSuccesses === 0) {
+2 -1
View File
@@ -86,7 +86,8 @@ export function range(start: number, end: number): number[] {
return result;
}
/// Returns the first argument that isn't `undefined`.
/// Returns the first argument that isn't `undefined`. Returns `undefined` if
/// none of the arguments are defined.
export function firstDefined(...args: any[]): any {
for (let arg of args) {
if (arg !== undefined) {