11<template >
2- <BlockUI ref =" blockUiRef " class =" opencor overflow-hidden h-full" :class =" isFullWebApp ? 'with-main-menu' : ''"
3- :blocked =" blockUiBlocked "
2+ <SafeBlockUI ref =" safeBlockUiRef " class =" opencor overflow-hidden h-full" :class =" isFullWebApp ? 'with-main-menu' : ''"
3+ :blocked =" compBlockUiEnabled "
44 @click =" activateInstance"
55 @focus =" activateInstance"
66 @focusin =" activateInstance"
9898 @close =" webUpdateAvailableVisible = false"
9999 />
100100 </div >
101- </BlockUI >
101+ </SafeBlockUI >
102102</template >
103103
104104<script setup lang="ts">
@@ -110,7 +110,6 @@ import firebase from 'firebase/compat/app';
110110import 'firebase/compat/auth';
111111import { Octokit } from 'octokit';
112112*/
113- import BlockUI from ' primevue/blockui' ;
114113import primeVueConfig from ' primevue/config' ;
115114import primeVueConfirmationService from ' primevue/confirmationservice' ;
116115import primeVueToastService from ' primevue/toastservice' ;
@@ -122,7 +121,7 @@ import type { IOpenCOREmits, IOpenCORProps } from '../../index.ts';
122121import ' ../assets/app.css' ;
123122import ' ../assets/primeicons-assets.ts' ;
124123import * as common from ' ../common/common.ts' ;
125- import { FULL_URI_SCHEME , LONG_DELAY , NO_DELAY , SHORT_DELAY , TOAST_LIFE } from ' ../common/constants.ts' ;
124+ import { FULL_URI_SCHEME , LONG_DELAY , SHORT_DELAY , TOAST_LIFE } from ' ../common/constants.ts' ;
126125import * as dependencies from ' ../common/dependencies.ts' ;
127126import { electronApi } from ' ../common/electronApi.ts' ;
128127/* TODO: enable once our GitHub integration is fully ready.
@@ -136,6 +135,7 @@ import ContentsComponent from '../components/ContentsComponent.vue';
136135import * as locApi from ' ../libopencor/locApi.ts' ;
137136
138137import { provideDialogState } from ' ./dialogs/BaseDialog.vue' ;
138+ import SafeBlockUI from ' ./widgets/SafeBlockUI.vue' ;
139139import MainMenu from ' ./MainMenu.vue' ;
140140
141141const props = defineProps <IOpenCORProps >();
@@ -203,7 +203,7 @@ const emitSimulationData = (): void => {
203203
204204const { isDialogActive } = provideDialogState ();
205205
206- const blockUiRef = vue .ref <InstanceType <typeof BlockUI > | null >(null );
206+ const safeBlockUiRef = vue .ref <InstanceType <typeof SafeBlockUI > | null >(null );
207207const mainMenuRef = vue .ref <InstanceType <typeof MainMenu > | null >(null );
208208const filesRef = vue .ref <HTMLElement | null >(null );
209209const contentsRef = vue .ref <InstanceType <typeof ContentsComponent > | null >(null );
@@ -259,35 +259,34 @@ const compUiEnabled = vue.computed<boolean>(() => {
259259 return ! compBlockUiEnabled .value && ! isDialogActive .value ;
260260});
261261
262- // Block/unblock the UI with "no" (i.e. a bit of a) delay to ensure that it doesn't happen too quickly (e.g., when
263- // loading a model from a COMBINE archive, we don't want the UI to be blocked for a split second while the file is
264- // being processed and the Simulation Experiment view is being shown in isolation).
265-
266- const blockUiBlocked = vue .ref <boolean >(true );
267- let blockUiBlockedTimeoutId: number | undefined ;
262+ // Remove any leftover SafeBlockUI masks when unblocking.
263+ // Note: this is to ensure that we don't end up with leftover masks if the block event is emitted multiple times before
264+ // the unblock event is emitted, which can lead to multiple masks being created and not properly removed.
268265
269266vue .watch (
270267 compBlockUiEnabled ,
271268 (newCompBlockUiEnabled : boolean ) => {
272- if (blockUiBlockedTimeoutId !== undefined ) {
273- window . clearTimeout ( blockUiBlockedTimeoutId ) ;
269+ if (! newCompBlockUiEnabled ) {
270+ const safeBlockUi = safeBlockUiRef . value as unknown as InstanceType < typeof SafeBlockUI > | null ;
274271
275- blockUiBlockedTimeoutId = undefined ;
276- }
272+ if (! safeBlockUi ) {
273+ return ;
274+ }
275+
276+ const safeBlockUiRoot = safeBlockUi ?.$el as HTMLElement | undefined ;
277+
278+ if (! safeBlockUiRoot ) {
279+ return ;
280+ }
277281
278- blockUiBlockedTimeoutId = window .setTimeout (() => {
279- blockUiBlocked .value = newCompBlockUiEnabled ;
280- }, NO_DELAY );
282+ for (const mask of safeBlockUiRoot .querySelectorAll <HTMLElement >(' .p-blockui-mask' )) {
283+ safeBlockUi .removeSpecificMask (mask );
284+ }
285+ }
281286 },
282287 { immediate: true }
283288);
284289
285- vue .onUnmounted (() => {
286- if (blockUiBlockedTimeoutId !== undefined ) {
287- window .clearTimeout (blockUiBlockedTimeoutId );
288- }
289- });
290-
291290// Determine whether we are running the full Web app (i.e. not in isolation).
292291
293292const isFullWebApp = vue .computed <boolean >(() => {
@@ -910,7 +909,7 @@ electronApi?.onSelect((filePath: string) => {
910909// A few things that can only be done when the component is mounted.
911910
912911vue .onMounted (() => {
913- const blockUiElement = (blockUiRef .value as unknown as { $el: HTMLElement })?.$el ;
912+ const safeBlockUiElement = (safeBlockUiRef .value as unknown as { $el: HTMLElement })?.$el ;
914913
915914 // Make ourselves the active instance.
916915
@@ -923,8 +922,8 @@ vue.onMounted(() => {
923922 setTimeout (() => {
924923 const toastElement = document .getElementById (toastId .value );
925924
926- if (toastElement && blockUiElement && toastElement .parentElement !== blockUiElement ) {
927- blockUiElement .appendChild (toastElement );
925+ if (toastElement && safeBlockUiElement && toastElement .parentElement !== safeBlockUiElement ) {
926+ safeBlockUiElement .appendChild (toastElement );
928927 }
929928 }, SHORT_DELAY );
930929});
@@ -940,10 +939,14 @@ vue.onMounted(() => {
940939
941940 void vue .nextTick (() => {
942941 const mainMenuElement = (mainMenuRef .value as unknown as { $el: HTMLElement })?.$el ;
943- const blockUiElement = (blockUiRef .value as unknown as { $el: HTMLElement })?.$el ;
944-
945- if (mainMenuElement && blockUiElement ) {
946- stopTrackingMainMenuHeight = vueCommon .trackElementHeight (mainMenuElement , blockUiElement , ' --main-menu-height' );
942+ const safeBlockUiElement = (safeBlockUiRef .value as unknown as { $el: HTMLElement })?.$el ;
943+
944+ if (mainMenuElement && safeBlockUiElement ) {
945+ stopTrackingMainMenuHeight = vueCommon .trackElementHeight (
946+ mainMenuElement ,
947+ safeBlockUiElement ,
948+ ' --main-menu-height'
949+ );
947950 }
948951 });
949952});
0 commit comments