@opencor/opencor 0.20250826.0 → 0.20250827.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/opencor.es.js +1 -1
  2. package/package.json +5 -6
  3. package/src/App.vue +0 -7
  4. package/src/ContainerApp.vue +0 -21
  5. package/src/assets/app.css +0 -14
  6. package/src/assets/base.css +0 -31
  7. package/src/assets/logo.svg +0 -17
  8. package/src/common/common.ts +0 -86
  9. package/src/common/constants.ts +0 -12
  10. package/src/common/electron.ts +0 -23
  11. package/src/common/electronApi.ts +0 -63
  12. package/src/common/locCommon.ts +0 -170
  13. package/src/common/settings.ts +0 -95
  14. package/src/common/vueCommon.ts +0 -69
  15. package/src/components/BackgroundComponent.vue +0 -26
  16. package/src/components/BlockingMessageComponent.vue +0 -34
  17. package/src/components/ContentsComponent.vue +0 -277
  18. package/src/components/DragNDropComponent.vue +0 -35
  19. package/src/components/MainMenu.vue +0 -225
  20. package/src/components/OpenCOR.vue +0 -624
  21. package/src/components/dialogs/AboutDialog.vue +0 -51
  22. package/src/components/dialogs/BaseDialog.vue +0 -58
  23. package/src/components/dialogs/OpenRemoteDialog.vue +0 -37
  24. package/src/components/dialogs/ResetAllDialog.vue +0 -13
  25. package/src/components/dialogs/SettingsDialog.vue +0 -42
  26. package/src/components/dialogs/UpdateAvailableDialog.vue +0 -16
  27. package/src/components/dialogs/UpdateDownloadProgressDialog.vue +0 -11
  28. package/src/components/dialogs/UpdateErrorDialog.vue +0 -18
  29. package/src/components/dialogs/UpdateNotAvailableDialog.vue +0 -12
  30. package/src/components/propertyEditors/GraphsPropertyEditor.vue +0 -3
  31. package/src/components/propertyEditors/ParametersPropertyEditor.vue +0 -3
  32. package/src/components/propertyEditors/PropertyEditor.vue +0 -60
  33. package/src/components/propertyEditors/SimulationPropertyEditor.vue +0 -45
  34. package/src/components/propertyEditors/SolversPropertyEditor.vue +0 -3
  35. package/src/components/views/IssuesView.vue +0 -50
  36. package/src/components/views/SimulationExperimentUiView.vue +0 -154
  37. package/src/components/views/SimulationExperimentView.vue +0 -218
  38. package/src/components/widgets/GraphPanelWidget.vue +0 -140
  39. package/src/components/widgets/InputWidget.vue +0 -128
  40. package/src/libopencor/locApi.ts +0 -167
  41. package/src/libopencor/locFileApi.ts +0 -263
  42. package/src/libopencor/locLoggerApi.ts +0 -36
  43. package/src/libopencor/locSedApi.ts +0 -486
  44. package/src/libopencor/locUiJsonApi.ts +0 -485
  45. package/src/libopencor/locVersionApi.ts +0 -17
  46. package/src/libopencor/src/common.cpp +0 -67
  47. package/src/libopencor/src/common.h +0 -27
  48. package/src/libopencor/src/file.cpp +0 -72
  49. package/src/libopencor/src/file.h +0 -15
  50. package/src/libopencor/src/main.cpp +0 -78
  51. package/src/libopencor/src/sed.cpp +0 -348
  52. package/src/libopencor/src/sed.h +0 -53
  53. package/src/libopencor/src/version.cpp +0 -8
  54. package/src/libopencor/src/version.h +0 -5
  55. package/src/main.ts +0 -6
  56. package/src/types/types.d.ts +0 -9
@@ -1,624 +0,0 @@
1
- <template>
2
- <BlockUI id="blockUi" :blocked="!uiEnabled" class="overflow-hidden" :style="blockUiStyle">
3
- <Toast id="toast" :pt:root:style="{ position: 'absolute' }" />
4
- <BackgroundComponent v-show="loadingOpencorMessageVisible || loadingModelMessageVisible || omex === undefined" />
5
- <BlockingMessageComponent message="Loading OpenCOR..." v-show="loadingOpencorMessageVisible" />
6
- <BlockingMessageComponent message="Loading model..." v-show="loadingModelMessageVisible" />
7
- <IssuesView v-if="issues.length !== 0" class="h-full" :issues="issues" :simulationOnly="omex !== undefined" />
8
- <div
9
- v-else
10
- @dragenter="onDragEnter"
11
- class="h-full"
12
- @dragover.prevent
13
- @drop.prevent="onDrop"
14
- @dragleave="onDragLeave"
15
- >
16
- <input ref="files" type="file" multiple style="display: none" @change="onChange" />
17
- <DragNDropComponent v-show="dragAndDropCounter > 0" />
18
- <div v-show="!electronApi && omex === undefined">
19
- <MainMenu
20
- v-show="mainMenuVisible"
21
- :uiEnabled="compUiEnabled"
22
- :hasFiles="hasFiles"
23
- @about="onAbout"
24
- @open="($refs.files as HTMLInputElement).click()"
25
- @openRemote="openRemoteVisible = true"
26
- @openSampleLorenz="onOpenSampleLorenz"
27
- @openSampleInteractiveLorenz="onOpenSampleInteractiveLorenz"
28
- @close="onClose"
29
- @closeAll="onCloseAll"
30
- @settings="onSettings"
31
- />
32
- </div>
33
- <ContentsComponent ref="contents" :uiEnabled="compUiEnabled" :simulationOnly="omex !== undefined" />
34
- <OpenRemoteDialog
35
- v-model:visible="openRemoteVisible"
36
- @openRemote="onOpenRemote"
37
- @close="openRemoteVisible = false"
38
- />
39
- <SettingsDialog v-model:visible="settingsVisible" @close="settingsVisible = false" />
40
- <ResetAllDialog v-model:visible="resetAllVisible" @resetAll="onResetAll" @close="resetAllVisible = false" />
41
- <AboutDialog v-model:visible="aboutVisible" @close="aboutVisible = false" />
42
- </div>
43
- <UpdateErrorDialog
44
- v-model:visible="updateErrorVisible"
45
- :title="updateErrorTitle"
46
- :issue="updateErrorIssue"
47
- @close="onUpdateErrorDialogClose"
48
- />
49
- <UpdateAvailableDialog
50
- v-model:visible="updateAvailableVisible"
51
- :version="updateVersion"
52
- @downloadAndInstall="onDownloadAndInstall"
53
- @close="updateAvailableVisible = false"
54
- />
55
- <UpdateDownloadProgressDialog v-model:visible="updateDownloadProgressVisible" :percent="updateDownloadPercent" />
56
- <UpdateNotAvailableDialog v-model:visible="updateNotAvailableVisible" @close="updateNotAvailableVisible = false" />
57
- </BlockUI>
58
- </template>
59
-
60
- <script setup lang="ts">
61
- import primeVueAuraTheme from '@primeuix/themes/aura'
62
- import * as vueusecore from '@vueuse/core'
63
-
64
- import 'primeicons/primeicons.css'
65
- import primeVueConfig from 'primevue/config'
66
- import primeVueConfirmationService from 'primevue/confirmationservice'
67
- import primeVueToastService from 'primevue/toastservice'
68
- import { useToast } from 'primevue/usetoast'
69
- import * as vue from 'vue'
70
-
71
- import type { IOpenCORProps } from '../../index'
72
-
73
- import '../assets/app.css'
74
- import * as common from '../common/common'
75
- import { SHORT_DELAY, TOAST_LIFE } from '../common/constants'
76
- import { electronApi } from '../common/electronApi'
77
- import * as locCommon from '../common/locCommon'
78
- import * as vueCommon from '../common/vueCommon'
79
- import IContentsComponent from '../components/ContentsComponent.vue'
80
- import * as locApi from '../libopencor/locApi'
81
-
82
- const props = defineProps<IOpenCORProps>()
83
-
84
- // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
85
- const contents = vue.ref<InstanceType<typeof IContentsComponent> | null>(null)
86
- const issues = vue.ref<locApi.IIssue[]>([])
87
-
88
- const compUiEnabled = vue.computed(() => {
89
- return (
90
- uiEnabled.value &&
91
- !openRemoteVisible.value &&
92
- !settingsVisible.value &&
93
- !resetAllVisible.value &&
94
- !aboutVisible.value &&
95
- !updateErrorVisible.value &&
96
- !updateAvailableVisible.value &&
97
- !updateDownloadProgressVisible.value &&
98
- !updateNotAvailableVisible.value
99
- )
100
- })
101
-
102
- // Get the current Vue app instance to use some PrimeVue components.
103
-
104
- const getCurrentInstance = vue.getCurrentInstance()
105
-
106
- if (getCurrentInstance !== null) {
107
- const app = getCurrentInstance.appContext.app
108
- let options = {}
109
-
110
- if (props.theme === 'light') {
111
- options = {
112
- darkModeSelector: false
113
- }
114
- } else if (props.theme === 'dark') {
115
- document.documentElement.classList.add('opencor-dark-mode')
116
- document.body.classList.add('opencor-dark-mode')
117
-
118
- options = {
119
- darkModeSelector: '.opencor-dark-mode'
120
- }
121
- }
122
-
123
- app.use(primeVueConfig as unknown as vue.Plugin, {
124
- theme: {
125
- preset: primeVueAuraTheme,
126
- options: options
127
- }
128
- })
129
- app.use(primeVueConfirmationService as unknown as vue.Plugin)
130
- app.use(primeVueToastService as unknown as vue.Plugin)
131
- }
132
-
133
- if (props.theme !== undefined) {
134
- vueCommon.setTheme(props.theme)
135
- }
136
-
137
- const toast = useToast()
138
-
139
- // Asynchronously initialise our libOpenCOR API.
140
-
141
- const locApiInitialised = vue.ref(false)
142
-
143
- void locApi.initialiseLocApi().then(() => {
144
- locApiInitialised.value = true
145
- })
146
-
147
- // Handle an action.
148
-
149
- electronApi?.onAction((action: string) => {
150
- handleAction(action)
151
- })
152
-
153
- function handleAction(action: string): void {
154
- function isAction(actionName: string, expectedActionName: string): boolean {
155
- return actionName.localeCompare(expectedActionName, undefined, { sensitivity: 'base' }) === 0
156
- }
157
-
158
- const index = action.indexOf('/')
159
- const actionName = index !== -1 ? action.substring(0, index) : action
160
- const actionArguments = index !== -1 ? action.substring(index + 1) : ''
161
-
162
- if (isAction(actionName, 'openAboutDialog')) {
163
- onAbout()
164
- } else if (isAction(actionName, 'openSettingsDialog')) {
165
- onSettings()
166
- } else {
167
- const filePaths = actionArguments.split('%7C')
168
-
169
- if (
170
- (isAction(actionName, 'openFile') && filePaths.length === 1) ||
171
- (isAction(actionName, 'openFiles') && filePaths.length > 1)
172
- ) {
173
- for (const filePath of filePaths) {
174
- openFile(filePath)
175
- }
176
- } else {
177
- toast.add({
178
- severity: 'error',
179
- summary: 'Handling an action',
180
- detail: `${action}\n\nThe action could not be handled.`,
181
- life: TOAST_LIFE
182
- })
183
- }
184
- }
185
- }
186
-
187
- // Enable/disable the UI.
188
-
189
- const uiEnabled = vue.ref<boolean>(true)
190
-
191
- electronApi?.onEnableDisableUi((enable: boolean) => {
192
- enableDisableUi(enable)
193
- })
194
-
195
- function enableDisableUi(enable: boolean): void {
196
- uiEnabled.value = enable
197
- }
198
-
199
- // Enable/disable some menu items.
200
-
201
- const hasFiles = vue.computed(() => {
202
- return contents.value?.hasFiles() ?? false
203
- })
204
-
205
- vue.watch(hasFiles, (hasFiles) => {
206
- electronApi?.enableDisableFileCloseAndCloseAllMenuItems(hasFiles)
207
- })
208
-
209
- // Loading OpenCOR.
210
- // Note: this is only done if window.locApi is not defined, which means that we are running OpenCOR's Web app.
211
-
212
- const loadingOpencorMessageVisible = vue.ref<boolean>(false)
213
-
214
- // @ts-expect-error (window.locApi may or may not be defined which is why we test it)
215
- if (window.locApi === undefined) {
216
- enableDisableUi(false)
217
-
218
- loadingOpencorMessageVisible.value = true
219
-
220
- vue.watch(locApiInitialised, (initialised) => {
221
- if (initialised) {
222
- loadingOpencorMessageVisible.value = false
223
-
224
- enableDisableUi(true)
225
- }
226
- })
227
- }
228
-
229
- // Loading model.
230
-
231
- const loadingModelMessageVisible = vue.ref<boolean>(false)
232
-
233
- function showLoadingModelMessage(): void {
234
- enableDisableUi(false)
235
-
236
- loadingModelMessageVisible.value = true
237
- }
238
-
239
- function hideLoadingModelMessage(): void {
240
- enableDisableUi(true)
241
-
242
- loadingModelMessageVisible.value = false
243
- }
244
-
245
- // Auto update.
246
-
247
- electronApi?.onCheckForUpdates(() => {
248
- electronApi?.checkForUpdates(false)
249
- })
250
-
251
- const updateErrorVisible = vue.ref<boolean>(false)
252
- const updateErrorTitle = vue.ref<string>('')
253
- const updateErrorIssue = vue.ref<string>('')
254
-
255
- function onUpdateErrorDialogClose(): void {
256
- updateErrorVisible.value = false
257
- updateDownloadProgressVisible.value = false
258
- }
259
-
260
- const updateAvailableVisible = vue.ref<boolean>(false)
261
- const updateDownloadProgressVisible = vue.ref<boolean>(false)
262
- const updateVersion = vue.ref<string>('')
263
- const updateDownloadPercent = vue.ref<number>(0)
264
-
265
- electronApi?.onUpdateAvailable((version: string) => {
266
- updateAvailableVisible.value = true
267
- updateVersion.value = version
268
- })
269
-
270
- function onDownloadAndInstall(): void {
271
- updateDownloadPercent.value = 0 // Just to be on the safe side.
272
- updateDownloadProgressVisible.value = true
273
- updateAvailableVisible.value = false
274
-
275
- electronApi?.downloadAndInstallUpdate()
276
- }
277
-
278
- electronApi?.onUpdateDownloadError((issue: string) => {
279
- updateErrorTitle.value = 'Downloading Update...'
280
- updateErrorIssue.value = `An error occurred while downloading the update (${issue}).`
281
- updateErrorVisible.value = true
282
- })
283
-
284
- electronApi?.onUpdateDownloadProgress((percent: number) => {
285
- updateDownloadPercent.value = percent
286
- })
287
-
288
- electronApi?.onUpdateDownloaded(() => {
289
- updateDownloadPercent.value = 100 // Just to be on the safe side.
290
-
291
- electronApi?.installUpdateAndRestart()
292
- })
293
-
294
- const updateNotAvailableVisible = vue.ref<boolean>(false)
295
-
296
- electronApi?.onUpdateNotAvailable(() => {
297
- updateNotAvailableVisible.value = true
298
- })
299
-
300
- electronApi?.onUpdateCheckError((issue: string) => {
301
- updateErrorTitle.value = 'Checking For Updates...'
302
- updateErrorIssue.value = `An error occurred while checking for updates (${issue}).`
303
- updateErrorVisible.value = true
304
- })
305
-
306
- // About dialog.
307
-
308
- const aboutVisible = vue.ref<boolean>(false)
309
-
310
- electronApi?.onAbout(() => {
311
- onAbout()
312
- })
313
-
314
- function onAbout(): void {
315
- aboutVisible.value = true
316
- }
317
-
318
- // Settings dialog.
319
-
320
- const settingsVisible = vue.ref<boolean>(false)
321
-
322
- electronApi?.onSettings(() => {
323
- onSettings()
324
- })
325
-
326
- function onSettings(): void {
327
- settingsVisible.value = true
328
- }
329
-
330
- // Open a file.
331
-
332
- function openFile(fileOrFilePath: string | File): void {
333
- // Check whether the file is already open and if so then select it.
334
-
335
- const filePath = locCommon.filePath(fileOrFilePath)
336
-
337
- if (contents.value?.hasFile(filePath) ?? false) {
338
- contents.value?.selectFile(filePath)
339
-
340
- return
341
- }
342
-
343
- // Retrieve a locApi.File object for the given file or file path and add it to the contents.
344
-
345
- if (locCommon.isRemoteFilePath(filePath)) {
346
- showLoadingModelMessage()
347
- }
348
-
349
- locCommon
350
- .file(fileOrFilePath)
351
- .then((file) => {
352
- const fileType = file.type()
353
-
354
- if (
355
- fileType === locApi.EFileType.IRRETRIEVABLE_FILE ||
356
- fileType === locApi.EFileType.UNKNOWN_FILE ||
357
- (props.omex !== undefined && fileType !== locApi.EFileType.COMBINE_ARCHIVE)
358
- ) {
359
- if (props.omex !== undefined) {
360
- void vue.nextTick().then(() => {
361
- issues.value.push({
362
- type: locApi.EIssueType.ERROR,
363
- description:
364
- fileType === locApi.EFileType.IRRETRIEVABLE_FILE
365
- ? 'The file could not be retrieved.'
366
- : 'Only COMBINE archives are supported.'
367
- })
368
- })
369
- } else {
370
- toast.add({
371
- severity: 'error',
372
- summary: 'Opening a file',
373
- detail:
374
- filePath +
375
- '\n\n' +
376
- (fileType === locApi.EFileType.IRRETRIEVABLE_FILE
377
- ? 'The file could not be retrieved.'
378
- : 'Only CellML files, SED-ML files, and COMBINE archives are supported.'),
379
- life: TOAST_LIFE
380
- })
381
- }
382
-
383
- electronApi?.fileIssue(filePath)
384
- } else {
385
- contents.value?.openFile(file)
386
- }
387
-
388
- if (locCommon.isRemoteFilePath(filePath)) {
389
- hideLoadingModelMessage()
390
- }
391
- })
392
- .catch((error: unknown) => {
393
- if (locCommon.isRemoteFilePath(filePath)) {
394
- hideLoadingModelMessage()
395
- }
396
-
397
- if (props.omex !== undefined) {
398
- void vue.nextTick().then(() => {
399
- issues.value.push({
400
- type: locApi.EIssueType.ERROR,
401
- description: common.formatIssue(error instanceof Error ? error.message : String(error))
402
- })
403
- })
404
- } else {
405
- toast.add({
406
- severity: 'error',
407
- summary: 'Opening a file',
408
- detail: `${filePath}\n\n${common.formatIssue(error instanceof Error ? error.message : String(error))}`,
409
- life: TOAST_LIFE
410
- })
411
- }
412
-
413
- electronApi?.fileIssue(filePath)
414
- })
415
- }
416
-
417
- // Open file(s) dialog.
418
-
419
- function onChange(event: Event): void {
420
- const files = (event.target as HTMLInputElement).files
421
-
422
- if (files !== null) {
423
- for (const file of Array.from(files)) {
424
- openFile(file)
425
- }
426
- }
427
- }
428
-
429
- // Drag and drop.
430
-
431
- const dragAndDropCounter = vue.ref<number>(0)
432
-
433
- function onDragEnter(): void {
434
- if (!uiEnabled.value || props.omex !== undefined) {
435
- return
436
- }
437
-
438
- dragAndDropCounter.value += 1
439
- }
440
-
441
- function onDrop(event: DragEvent): void {
442
- if (dragAndDropCounter.value === 0) {
443
- return
444
- }
445
-
446
- dragAndDropCounter.value = 0
447
-
448
- const files = event.dataTransfer?.files
449
-
450
- if (files !== undefined) {
451
- for (const file of Array.from(files)) {
452
- openFile(file)
453
- }
454
- }
455
- }
456
-
457
- function onDragLeave(): void {
458
- if (dragAndDropCounter.value === 0) {
459
- return
460
- }
461
-
462
- dragAndDropCounter.value -= 1
463
- }
464
-
465
- // Open.
466
-
467
- electronApi?.onOpen((filePath: string) => {
468
- openFile(filePath)
469
- })
470
-
471
- // Open remote.
472
-
473
- const openRemoteVisible = vue.ref<boolean>(false)
474
-
475
- electronApi?.onOpenRemote(() => {
476
- openRemoteVisible.value = true
477
- })
478
-
479
- function onOpenRemote(url: string): void {
480
- // Note: no matter whether this is OpenCOR or OpenCOR's Web app, we always retrieve the file contents of a remote
481
- // file. We could, in OpenCOR, rely on libOpenCOR to retrieve it for us, but this would block the UI. To
482
- // retrieve the file here means that it is done asynchronously, which in turn means that the UI is not blocked
483
- // and that we can show a spinning wheel to indicate that something is happening.
484
-
485
- openFile(url)
486
- }
487
-
488
- // Open sample Lorenz.
489
-
490
- electronApi?.onOpenSampleLorenz(() => {
491
- onOpenSampleLorenz()
492
- })
493
-
494
- function onOpenSampleLorenz(): void {
495
- openFile('https://github.com/opencor/webapp/raw/refs/heads/main/tests/models/lorenz.omex')
496
- }
497
-
498
- // Open sample interactive Lorenz.
499
-
500
- electronApi?.onOpenSampleInteractiveLorenz(() => {
501
- onOpenSampleInteractiveLorenz()
502
- })
503
-
504
- function onOpenSampleInteractiveLorenz(): void {
505
- openFile('https://github.com/opencor/webapp/raw/refs/heads/main/tests/models/ui/lorenz.omex')
506
- }
507
-
508
- // Close.
509
-
510
- electronApi?.onClose(() => {
511
- onClose()
512
- })
513
-
514
- function onClose(): void {
515
- contents.value?.closeCurrentFile()
516
- }
517
-
518
- // Close all.
519
-
520
- electronApi?.onCloseAll(() => {
521
- onCloseAll()
522
- })
523
-
524
- function onCloseAll(): void {
525
- contents.value?.closeAllFiles()
526
- }
527
-
528
- // Reset all.
529
-
530
- const resetAllVisible = vue.ref<boolean>(false)
531
-
532
- electronApi?.onResetAll(() => {
533
- resetAllVisible.value = true
534
- })
535
-
536
- function onResetAll(): void {
537
- electronApi?.resetAll()
538
- }
539
-
540
- // Select.
541
-
542
- electronApi?.onSelect((filePath: string) => {
543
- contents.value?.selectFile(filePath)
544
- })
545
-
546
- // Track the height of our block UI.
547
-
548
- vueCommon.trackElementHeight('blockUi')
549
-
550
- // Set the height of our block UI.
551
-
552
- const blockUiStyle = vue.ref({})
553
- const mainMenuVisible = vue.ref<boolean>(false)
554
-
555
- vue.onMounted(() => {
556
- // Set the height of our block UI to either '100vh' or '100%', depending on the height of our document element.
557
-
558
- blockUiStyle.value =
559
- window.getComputedStyle(document.documentElement).height === '0px' ? { height: '100vh' } : { height: '100%' }
560
-
561
- // We have set the height of our block UI, so we can now safely show our main menu.
562
- // Note: indeed, to properly determine the height of our document element, we must ensure that our own height is zero.
563
-
564
- mainMenuVisible.value = true
565
- })
566
-
567
- // If a COMBINE archive is provided then open it (and then the Simulation Experiment view will be shown in isolation) or
568
- // carry as normal (i.e. the whole OpenCOR UI will be shown).
569
-
570
- if (props.omex !== undefined) {
571
- vue.watch(locApiInitialised, (initialised) => {
572
- if (initialised) {
573
- if (props.omex !== undefined) {
574
- openFile(props.omex)
575
- }
576
- }
577
- })
578
- } else {
579
- // (Also) track the height of our main menu.
580
-
581
- vueCommon.trackElementHeight('mainMenu')
582
-
583
- // Things that need to be done when the component is mounted.
584
-
585
- vue.onMounted(() => {
586
- // Do what follows with a bit of a delay to give our background (with the OpenCOR logo) time to be renderered.
587
-
588
- setTimeout(() => {
589
- // Ensure that our toasts are shown within our container.
590
-
591
- const toastElement = document.getElementById('toast')
592
- const blockUiElement = document.getElementById('blockUi')
593
-
594
- if (toastElement !== null && blockUiElement !== null) {
595
- blockUiElement.appendChild(toastElement)
596
- }
597
-
598
- if (electronApi !== undefined) {
599
- // Check for updates.
600
- // Note: the main process will actually check for updates if requested and if OpenCOR is packaged.
601
-
602
- electronApi.checkForUpdates(true)
603
- } else {
604
- // Handle the action passed to our Web app, if any.
605
- // Note: to use vue.nextTick() doesn't do the trick, so we have no choice but to use setTimeout().
606
-
607
- const action = vueusecore.useStorage('action', '')
608
-
609
- if (window.location.search !== '') {
610
- action.value = window.location.search.substring(1)
611
-
612
- window.location.search = ''
613
- } else if (action.value !== '') {
614
- setTimeout(() => {
615
- handleAction(action.value)
616
-
617
- action.value = ''
618
- }, SHORT_DELAY)
619
- }
620
- }
621
- }, SHORT_DELAY)
622
- })
623
- }
624
- </script>
@@ -1,51 +0,0 @@
1
- <template>
2
- <BaseDialog header=" " style="width: 39rem">
3
- <div class="space-y-7">
4
- <div class="text-center">
5
- <div class="text-3xl font-bold">OpenCOR {{ version }}</div>
6
- <div v-if="electronApi !== undefined" class="text-xl italic font-bold">{{ electronApi.operatingSystem() }}</div>
7
- <div class="text-sm italic">Copyright {{ constants.COPYRIGHT }}</div>
8
- </div>
9
- <div class="space-y-2">
10
- <div>
11
- <a href="https://opencor.ws/" target="_blank" rel="noopener">OpenCOR</a> is a frontend to
12
- <a href="https://opencor.ws/libopencor/" target="_blank" rel="noopener">libOpenCOR</a> {{ locApi.version() }},
13
- a library that can be used to organise, edit, simulate, and analyse
14
- <a href="https://cellml.org/" target="_blank" rel="noopener">CellML</a> files.
15
- </div>
16
- <div class="space-y-0">
17
- <div>There are two versions of OpenCOR:</div>
18
-
19
- <ol class="list-decimal list-inside ml-2">
20
- <li>
21
- <span class="font-bold">OpenCOR:</span> a desktop application that can be run on
22
- <a href="https://en.wikipedia.org/wiki/List_of_Intel_processors">Intel</a>-based and
23
- <a href="https://en.wikipedia.org/wiki/ARM_architecture_family">ARM</a>-based
24
- <a href="https://en.wikipedia.org/wiki/Microsoft_Windows" target="_blank" rel="noopener">Windows</a>,
25
- <a href="https://en.wikipedia.org/wiki/Linux" target="_blank" rel="noopener">Linux</a>, and
26
- <a href="https://en.wikipedia.org/wiki/MacOS" target="_blank" rel="noopener">macOS</a> machines; and
27
- </li>
28
- <li>
29
- <span class="font-bold">OpenCOR's Web app:</span> a
30
- <a href="https://en.wikipedia.org/wiki/Web_application" target="_blank" rel="noopener">Web app</a> that
31
- can be run on a Web browser.
32
- </li>
33
- </ol>
34
- </div>
35
- </div>
36
- </div>
37
- <template #footer>
38
- <Button label="OK" autofocus @click="$emit('close')" />
39
- </template>
40
- </BaseDialog>
41
- </template>
42
-
43
- <script setup lang="ts">
44
- import * as constants from '../../common/constants'
45
- import { electronApi } from '../../common/electronApi'
46
- import * as locApi from '../../libopencor/locApi'
47
-
48
- defineEmits(['close'])
49
-
50
- import { version } from '../../../package.json'
51
- </script>