From 0da463a03a8d1628f555c72b3d800f8d5ac7f4f7 Mon Sep 17 00:00:00 2001 From: Jakob Pinterits Date: Sat, 27 Jul 2024 20:02:37 +0200 Subject: [PATCH] added missing supercalls and related fixes --- frontend/code/componentManagement.ts | 16 +++++----------- .../code/components/aspectRatioContainer.ts | 2 ++ frontend/code/components/buttons.ts | 2 ++ frontend/code/components/componentTree.ts | 2 ++ frontend/code/components/dialog_container.ts | 11 ++++++++--- frontend/code/components/layoutDisplay.ts | 2 ++ frontend/code/components/linearContainers.ts | 2 ++ frontend/code/components/mediaPlayer.ts | 2 ++ frontend/code/components/overlay.ts | 1 + frontend/code/components/plot.ts | 2 ++ frontend/code/components/popup.ts | 1 - frontend/code/components/switcherBar.ts | 1 + frontend/code/components/tooltip.ts | 1 - rio/dialog.py | 18 +++++++++++++----- rio/session.py | 3 ++- 15 files changed, 44 insertions(+), 22 deletions(-) diff --git a/frontend/code/componentManagement.ts b/frontend/code/componentManagement.ts index 901500f6..a6859d18 100644 --- a/frontend/code/componentManagement.ts +++ b/frontend/code/componentManagement.ts @@ -359,16 +359,7 @@ export function updateComponentStates( continue; } - // Destruct the component and all its children - let queue = [component]; - - for (let comp of queue) { - queue.push(...comp.children); - - comp.onDestruction(); - delete componentsById[comp.id]; - componentsByElement.delete(comp.element); - } + recursivelyDeleteComponent(component); } // If this is the first time, check if there's an #url-fragment and scroll @@ -395,7 +386,7 @@ export function recursivelyDeleteComponent(component: ComponentBase): void { // If this component had any dialogs attached, they must also go for (let dialog of comp.ownedDialogs) { - dialog.onDestruction(); + to_do.push(dialog); // Inform Python about the destruction of the dialog callRemoteMethodDiscardResponse('dialogRemoved', { @@ -409,6 +400,9 @@ export function recursivelyDeleteComponent(component: ComponentBase): void { // Remove it from the global lookup tables delete componentsById[comp.id]; componentsByElement.delete(comp.element); + + // And finally, remove it from the DOM + comp.element.remove(); } } diff --git a/frontend/code/components/aspectRatioContainer.ts b/frontend/code/components/aspectRatioContainer.ts index 7acfa4e5..f717a580 100644 --- a/frontend/code/components/aspectRatioContainer.ts +++ b/frontend/code/components/aspectRatioContainer.ts @@ -47,6 +47,8 @@ export class AspectRatioContainerComponent extends ComponentBase { } onDestruction(): void { + super.onDestruction(); + this.parentResizeObserver.disconnect(); this.childResizeObserver.disconnect(); } diff --git a/frontend/code/components/buttons.ts b/frontend/code/components/buttons.ts index d0820e06..a72e2616 100644 --- a/frontend/code/components/buttons.ts +++ b/frontend/code/components/buttons.ts @@ -167,6 +167,8 @@ export class IconButtonComponent extends AbstractButtonComponent { } onDestruction(): void { + super.onDestruction(); + this.resizeObserver.disconnect(); } diff --git a/frontend/code/components/componentTree.ts b/frontend/code/components/componentTree.ts index 3498ad77..e7e818dc 100644 --- a/frontend/code/components/componentTree.ts +++ b/frontend/code/components/componentTree.ts @@ -43,6 +43,8 @@ export class ComponentTreeComponent extends ComponentBase { } onDestruction(): void { + super.onDestruction(); + // Unregister this component from the global dev tools component console.assert(devToolsConnector !== null); devToolsConnector!.componentIdsToComponentTrees.delete(this.id); diff --git a/frontend/code/components/dialog_container.ts b/frontend/code/components/dialog_container.ts index cf67530d..1005795f 100644 --- a/frontend/code/components/dialog_container.ts +++ b/frontend/code/components/dialog_container.ts @@ -29,10 +29,15 @@ export class DialogContainerComponent extends ComponentBase { } onDestruction(): void { - console.debug('DESTROYED!'); + super.onDestruction(); - // Remove the element from the DOM - this.element.remove(); + // Animate the element + this.element.classList.remove('rio-dialog-container-enter'); + + // Then, remove the element from the DOM + setTimeout(() => { + this.element.remove(); + }, 2000); } updateElement( diff --git a/frontend/code/components/layoutDisplay.ts b/frontend/code/components/layoutDisplay.ts index 05f4c6de..64769424 100644 --- a/frontend/code/components/layoutDisplay.ts +++ b/frontend/code/components/layoutDisplay.ts @@ -91,6 +91,8 @@ export class LayoutDisplayComponent extends ComponentBase { } onDestruction(): void { + super.onDestruction(); + // Destroy the highlighter this.highlighter.destroy(); } diff --git a/frontend/code/components/linearContainers.ts b/frontend/code/components/linearContainers.ts index 66ea1604..ae4d3464 100644 --- a/frontend/code/components/linearContainers.ts +++ b/frontend/code/components/linearContainers.ts @@ -42,6 +42,8 @@ export abstract class LinearContainer extends ComponentBase { private spacerResizeObserver: OnlyResizeObserver | null = null; onDestruction(): void { + super.onDestruction(); + if (this.selfResizeObserver !== null) { this.selfResizeObserver.disconnect(); } diff --git a/frontend/code/components/mediaPlayer.ts b/frontend/code/components/mediaPlayer.ts index 9d555d04..548e6651 100644 --- a/frontend/code/components/mediaPlayer.ts +++ b/frontend/code/components/mediaPlayer.ts @@ -840,6 +840,8 @@ export class MediaPlayerComponent extends ComponentBase { } onDestruction(): void { + super.onDestruction(); + // Explicitly unload the video, just in case someone is still holding a // reference to this component or element this.mediaPlayer.pause(); diff --git a/frontend/code/components/overlay.ts b/frontend/code/components/overlay.ts index 1fc25910..9ae6288b 100644 --- a/frontend/code/components/overlay.ts +++ b/frontend/code/components/overlay.ts @@ -27,6 +27,7 @@ export class OverlayComponent extends ComponentBase { } onDestruction(): void { + super.onDestruction(); this.overlayElement.remove(); } diff --git a/frontend/code/components/plot.ts b/frontend/code/components/plot.ts index 9214da9d..ab850577 100644 --- a/frontend/code/components/plot.ts +++ b/frontend/code/components/plot.ts @@ -72,6 +72,8 @@ export class PlotComponent extends ComponentBase { } onDestruction(): void { + super.onDestruction(); + if (this.plotManager !== null) { this.plotManager.destroy(); } diff --git a/frontend/code/components/popup.ts b/frontend/code/components/popup.ts index c3a9dcce..52ae083a 100644 --- a/frontend/code/components/popup.ts +++ b/frontend/code/components/popup.ts @@ -116,7 +116,6 @@ export class PopupComponent extends ComponentBase { onDestruction(): void { super.onDestruction(); - this.popupManager.destroy(); } } diff --git a/frontend/code/components/switcherBar.ts b/frontend/code/components/switcherBar.ts index 4d482d8c..da9fb272 100644 --- a/frontend/code/components/switcherBar.ts +++ b/frontend/code/components/switcherBar.ts @@ -80,6 +80,7 @@ export class SwitcherBarComponent extends ComponentBase { } onDestruction(): void { + super.onDestruction(); this.resizeObserver.disconnect(); } diff --git a/frontend/code/components/tooltip.ts b/frontend/code/components/tooltip.ts index 424f9a7a..8791d003 100644 --- a/frontend/code/components/tooltip.ts +++ b/frontend/code/components/tooltip.ts @@ -84,7 +84,6 @@ export class TooltipComponent extends ComponentBase { onDestruction(): void { super.onDestruction(); - this.popupManager.destroy(); } } diff --git a/rio/dialog.py b/rio/dialog.py index 939fed69..0601e82c 100644 --- a/rio/dialog.py +++ b/rio/dialog.py @@ -14,24 +14,32 @@ class Dialog: async def remove(self) -> None: """ - Removes the dialog from the screen. + Removes the dialog from the screen. Has no effect if the dialog has + already been removed. """ # Dialogs are registered with their owning component. Remove them from # there. + # + # First, try to get the owning component from the session. Since it + # holds a reference to the dialog, if it can't be found, the dialog must + # have already been removed previously. session = self._root_component.session owning_component = session._weak_components_by_id.get( self._root_component._id, ) - assert owning_component is not None - # Try to remove the dialog from its owning component. If this fails, the - # dialog has already been removed before + if owning_component is None: + return + + # Try to remove the dialog from its owning component. This can of course + # fail if the dialog has already been removed. try: del owning_component._owned_dialogs_[self._root_component._id] except KeyError: return - # Tell the client to remove the dialog + # The dialog was just discarded on the Python side. Tell teh client to + # also remove it. await self._root_component.session._remove_dialog( self._root_component._id, ) diff --git a/rio/session.py b/rio/session.py index e9c6e7f8..78313aff 100644 --- a/rio/session.py +++ b/rio/session.py @@ -2454,11 +2454,12 @@ a.remove(); assert isinstance( dialog_container, rio.DialogContainer ), dialog_container + owning_component = self._weak_components_by_id[ dialog_container.owning_component_id ] - # Don't die to network lag... + # Still don't die to network lag if owning_component is None: return