From a1d12e840f9a9efd03259296b95b4a048299de05 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 24 Feb 2026 14:37:50 +1300 Subject: [PATCH 1/6] New version. --- package.json | 2 +- src/renderer/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index dfdd9b2f..b0e59a62 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "url": "git+https://github.com/opencor/webapp.git" }, "type": "module", - "version": "0.20260224.0", + "version": "0.20260224.1", "scripts": { "archive:web": "bun src/renderer/scripts/archive.web.js", "build": "electron-vite build", diff --git a/src/renderer/package.json b/src/renderer/package.json index fc5ccf1d..e5fd5b3d 100644 --- a/src/renderer/package.json +++ b/src/renderer/package.json @@ -39,7 +39,7 @@ }, "./style.css": "./dist/opencor.css" }, - "version": "0.20260224.0", + "version": "0.20260224.1", "scripts": { "build": "vite build && bun scripts/generate.version.js", "build:lib": "vite build --config vite.lib.config.ts && cp index.d.ts dist/index.d.ts", From 374ae3beac205ec20c447ec1e7602c2b0865ca8b Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 24 Feb 2026 12:41:30 +1300 Subject: [PATCH 2/6] Some minor cleaning up. --- src/renderer/src/components/OpenCOR.vue | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/renderer/src/components/OpenCOR.vue b/src/renderer/src/components/OpenCOR.vue index 62504c87..b9708b1d 100644 --- a/src/renderer/src/components/OpenCOR.vue +++ b/src/renderer/src/components/OpenCOR.vue @@ -21,7 +21,7 @@ > - (null); const toastId = vue.ref('opencorToast'); const mainMenu = vue.ref(null); -const mainMenuId = vue.ref('opencorMainMenu'); const files = vue.ref(null); const contents = vue.ref | null>(null); const issues = vue.ref([]); @@ -843,7 +842,6 @@ vue.onMounted(() => { // Customise our IDs. toastId.value = `opencorToast${crtInstanceUid}`; - mainMenuId.value = `opencorMainMenu${crtInstanceUid}`; // Make ourselves the active instance. From 7ea5a0982dd5cacce9c5efe0e7b86055f59b9e03 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 24 Feb 2026 13:38:32 +1300 Subject: [PATCH 3/6] OpenCOR: make sure that toasts get shown and in the correct instance. --- src/renderer/src/components/OpenCOR.vue | 48 +++++++++++-------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/src/renderer/src/components/OpenCOR.vue b/src/renderer/src/components/OpenCOR.vue index b9708b1d..01a9949e 100644 --- a/src/renderer/src/components/OpenCOR.vue +++ b/src/renderer/src/components/OpenCOR.vue @@ -141,7 +141,6 @@ const props = defineProps(); const { isDialogActive } = provideDialogState(); const blockUi = vue.ref(null); -const toastId = vue.ref('opencorToast'); const mainMenu = vue.ref(null); const files = vue.ref(null); const contents = vue.ref | null>(null); @@ -302,7 +301,17 @@ if (crtVueAppInstance) { vueCommon.useTheme().setTheme(props.theme); +// Get ready to show toasts and provide a helper to show them that ensures that the proper group id is used and that the +// instance becomes active before the message is pushed. + const toast = useToast(); +const toastId = vue.ref(`opencorToast${crtInstanceUid}`); + +const addToast = (options: Parameters[0]) => { + activateInstance(); + + toast.add({ ...options, group: toastId.value }); +}; // Finish initialising OpenCOR. @@ -408,9 +417,8 @@ const handleAction = (action: string): void => { openFile(filePath); } } else { - toast.add({ + addToast({ severity: 'error', - group: toastId.value, summary: 'Handling an action', detail: `${action}\n\nThe action could not be handled.`, life: TOAST_LIFE @@ -493,9 +501,8 @@ electronApi?.onUpdateCheckError((issue: string) => { // Handle errors. const onError = (message: string): void => { - toast.add({ + addToast({ severity: 'error', - group: toastId.value, summary: 'Error', detail: message, life: TOAST_LIFE @@ -555,9 +562,8 @@ const openFile = (fileFilePathOrFileContents: string | Uint8Array | File): void locCommon.zipCellmlDataUrl(fileFilePathOrFileContents).then((zipCellmlDataUriInfo: locCommon.IDataUriInfo) => { if (zipCellmlDataUriInfo.res) { if (zipCellmlDataUriInfo.error) { - toast.add({ + addToast({ severity: 'error', - group: toastId.value, summary: 'Opening a file', detail: zipCellmlDataUriInfo.error, life: TOAST_LIFE @@ -575,9 +581,8 @@ const openFile = (fileFilePathOrFileContents: string | Uint8Array | File): void if (combineArchiveDataUriInfo.res) { if (combineArchiveDataUriInfo.error) { - toast.add({ + addToast({ severity: 'error', - group: toastId.value, summary: 'Opening a file', detail: combineArchiveDataUriInfo.error, life: TOAST_LIFE @@ -631,9 +636,8 @@ const openFile = (fileFilePathOrFileContents: string | Uint8Array | File): void }); }); } else { - toast.add({ + addToast({ severity: 'error', - group: toastId.value, summary: 'Opening a file', detail: filePath + @@ -661,9 +665,8 @@ const openFile = (fileFilePathOrFileContents: string | Uint8Array | File): void }); }); } else { - toast.add({ + addToast({ severity: 'error', - group: toastId.value, summary: 'Opening a file', detail: `${filePath}\n\n${common.formatMessage(common.formatError(error))}`, life: TOAST_LIFE @@ -839,10 +842,6 @@ electronApi?.onSelect((filePath: string) => { vue.onMounted(() => { const blockUiElement = blockUi.value?.$el as HTMLElement; - // Customise our IDs. - - toastId.value = `opencorToast${crtInstanceUid}`; - // Make ourselves the active instance. setTimeout(() => { @@ -940,9 +939,8 @@ if (props.omex) { if (action.value.startsWith(FULL_URI_SCHEME)) { handleAction(action.value.slice(FULL_URI_SCHEME.length)); } else { - toast.add({ + addToast({ severity: 'error', - group: toastId.value, summary: 'Handling an action', detail: `${action.value}\n\nThe action could not be handled.`, life: TOAST_LIFE @@ -1027,18 +1025,16 @@ const saveGitHubAccessToken = async (accessToken: string): Promise => { const stored = await electronApi.saveGitHubAccessToken(accessToken); if (!stored) { - toast.add({ + addToast({ severity: 'warn', - group: toastId.value, summary: 'Remembering GitHub access token', detail: 'The token could not be stored securely, so you will need to sign in again next time.', life: TOAST_LIFE }); } } catch (error: unknown) { - toast.add({ + addToast({ severity: 'warn', - group: toastId.value, summary: 'Remembering GitHub access token', detail: common.formatMessage(common.formatError(error)), life: TOAST_LIFE @@ -1081,9 +1077,8 @@ const onDisconnectFromGitHub = async (): Promise => { await electronApi.clearGitHubCache(); } } catch (error: unknown) { - toast.add({ + addToast({ severity: 'error', - group: toastId.value, summary: 'GitHub sign-out', detail: common.formatMessage(common.formatError(error)), life: TOAST_LIFE @@ -1124,9 +1119,8 @@ const onGitHubButtonClick = async (): Promise => { await checkGitHubAccessToken(accessToken); } catch (error: unknown) { - toast.add({ + addToast({ severity: 'error', - group: toastId.value, summary: 'GitHub sign-in', detail: common.formatMessage(common.formatError(error)), life: TOAST_LIFE From 1bcab51c5b639e4e3f79160141f1ab5ab9bf1932 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 24 Feb 2026 13:46:50 +1300 Subject: [PATCH 4/6] Cleaned up our use of references and IDs. --- .../src/components/ContentsComponent.vue | 22 +----- src/renderer/src/components/MainMenu.vue | 12 +-- src/renderer/src/components/OpenCOR.vue | 47 ++++++------ ...SimulationExperimentViewSettingsDialog.vue | 19 ++--- .../views/SimulationExperimentView.vue | 43 ++++------- .../components/widgets/GraphPanelWidget.vue | 76 +++++++++---------- 6 files changed, 94 insertions(+), 125 deletions(-) diff --git a/src/renderer/src/components/ContentsComponent.vue b/src/renderer/src/components/ContentsComponent.vue index df4af653..7f2252a0 100644 --- a/src/renderer/src/components/ContentsComponent.vue +++ b/src/renderer/src/components/ContentsComponent.vue @@ -21,7 +21,7 @@ :scrollable="true" :selectOnFocus="true" > - + (); defineEmits<(event: 'error', message: string) => void>(); -export interface IContentsComponent { - openFile(file: locApi.File): void; - closeCurrentFile(): void; - closeAllFiles(): void; - hasFile(filePath: string): boolean; - hasFiles(): boolean; - selectFile(filePath: string): void; -} - -const fileTablistId = vue.ref('contentsComponentFileTablist'); const fileTabs = vue.ref([]); const activeFile = vue.ref(''); @@ -201,16 +191,6 @@ vue.watch(activeFile, (newActiveFile: string) => { electronApi?.fileSelected(newActiveFile); }); -// Various things that need to be done once we are mounted. - -const crtInstance = vue.getCurrentInstance(); - -vue.onMounted(() => { - // Customise our IDs. - - fileTablistId.value = `contentsComponentFileTablist${String(crtInstance?.uid)}`; -}); - // Keyboard shortcuts. if (common.isDesktop()) { diff --git a/src/renderer/src/components/MainMenu.vue b/src/renderer/src/components/MainMenu.vue index 28f0f65f..c1d61765 100644 --- a/src/renderer/src/components/MainMenu.vue +++ b/src/renderer/src/components/MainMenu.vue @@ -1,5 +1,5 @@