@electerm/electerm-react 3.1.16 → 3.2.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.
- package/client/common/db.js +10 -5
- package/client/components/ai/ai-history.jsx +4 -4
- package/client/components/bookmark-form/common/bookmark-select.jsx +18 -2
- package/client/components/bookmark-form/common/connection-hopping-form.jsx +153 -0
- package/client/components/bookmark-form/common/connection-hopping.jsx +136 -129
- package/client/components/bookmark-form/common/quick-commands.jsx +5 -4
- package/client/components/quick-commands/qm.styl +0 -2
- package/client/components/quick-commands/quick-commands-list-form.jsx +1 -1
- package/client/components/setting-panel/hotkey.jsx +9 -1
- package/client/components/setting-panel/list.jsx +0 -1
- package/client/components/setting-panel/list.styl +4 -0
- package/client/components/setting-panel/setting-modal.jsx +53 -47
- package/client/components/shortcuts/shortcut-editor.jsx +4 -2
- package/client/components/sidebar/history.jsx +1 -0
- package/client/components/terminal/attach-addon-custom.js +86 -0
- package/client/components/terminal/cmd-item.jsx +13 -3
- package/client/components/terminal/drop-file-modal.jsx +57 -0
- package/client/components/terminal/terminal-command-dropdown.jsx +91 -13
- package/client/components/terminal/terminal.jsx +103 -5
- package/client/components/terminal/terminal.styl +9 -0
- package/client/components/tree-list/tree-list-item.jsx +0 -1
- package/client/components/vnc/vnc-session.jsx +2 -0
- package/client/components/widgets/widget-control.jsx +3 -0
- package/client/components/widgets/widget-instance.jsx +26 -7
- package/client/css/includes/box.styl +3 -0
- package/client/store/init-state.js +3 -1
- package/client/store/load-data.js +9 -0
- package/client/store/mcp-handler.js +18 -0
- package/client/store/sync.js +3 -5
- package/client/store/watch.js +2 -2
- package/client/store/widgets.js +54 -0
- package/package.json +1 -1
|
@@ -19,7 +19,8 @@ import {
|
|
|
19
19
|
isWin,
|
|
20
20
|
rendererTypes,
|
|
21
21
|
isMac,
|
|
22
|
-
isMacJs
|
|
22
|
+
isMacJs,
|
|
23
|
+
connectionMap
|
|
23
24
|
} from '../../common/constants.js'
|
|
24
25
|
import deepCopy from 'json-deep-copy'
|
|
25
26
|
import { readClipboardAsync, readClipboard, copy } from '../../common/clipboard.js'
|
|
@@ -27,6 +28,7 @@ import AttachAddon from './attach-addon-custom.js'
|
|
|
27
28
|
import getProxy from '../../common/get-proxy.js'
|
|
28
29
|
import { ZmodemClient } from './zmodem-client.js'
|
|
29
30
|
import { TrzszClient } from './trzsz-client.js'
|
|
31
|
+
import DropFileModal from './drop-file-modal.jsx'
|
|
30
32
|
import keyControlPressed from '../../common/key-control-pressed.js'
|
|
31
33
|
import NormalBuffer from './normal-buffer.jsx'
|
|
32
34
|
import { createTerm, resizeTerm } from './terminal-apis.js'
|
|
@@ -75,7 +77,9 @@ class Term extends Component {
|
|
|
75
77
|
searchResults: [],
|
|
76
78
|
matchIndex: -1,
|
|
77
79
|
totalLines: 0,
|
|
78
|
-
reconnectCountdown: null
|
|
80
|
+
reconnectCountdown: null,
|
|
81
|
+
dropFileModalVisible: false,
|
|
82
|
+
droppedFiles: []
|
|
79
83
|
}
|
|
80
84
|
this.id = `term-${this.props.tab.id}`
|
|
81
85
|
refs.add(this.id, this)
|
|
@@ -392,9 +396,9 @@ class Term extends Component {
|
|
|
392
396
|
const dt = e.dataTransfer
|
|
393
397
|
const fromFile = dt.getData('fromFile')
|
|
394
398
|
const notSafeMsg = 'File name contains unsafe characters'
|
|
399
|
+
const isSshTerminal = this.props.tab.type === connectionMap.ssh
|
|
395
400
|
|
|
396
401
|
if (fromFile) {
|
|
397
|
-
// Handle SFTP file drop
|
|
398
402
|
try {
|
|
399
403
|
const fileData = JSON.parse(fromFile)
|
|
400
404
|
const filePath = resolve(fileData.path, fileData.name)
|
|
@@ -402,6 +406,13 @@ class Term extends Component {
|
|
|
402
406
|
message.error(notSafeMsg)
|
|
403
407
|
return
|
|
404
408
|
}
|
|
409
|
+
if (isSshTerminal) {
|
|
410
|
+
this.setState({
|
|
411
|
+
dropFileModalVisible: true,
|
|
412
|
+
droppedFiles: [{ path: filePath, isRemote: true }]
|
|
413
|
+
})
|
|
414
|
+
return
|
|
415
|
+
}
|
|
405
416
|
this.attachAddon._sendData(`"${filePath}" `)
|
|
406
417
|
return
|
|
407
418
|
} catch (e) {
|
|
@@ -409,24 +420,78 @@ class Term extends Component {
|
|
|
409
420
|
}
|
|
410
421
|
}
|
|
411
422
|
|
|
412
|
-
// Handle regular file drop
|
|
413
423
|
const files = dt.files
|
|
414
424
|
if (files && files.length) {
|
|
415
425
|
const arr = Array.from(files)
|
|
416
426
|
const filePaths = arr.map(f => getFilePath(f))
|
|
417
427
|
|
|
418
|
-
// Check each file path individually
|
|
419
428
|
const hasUnsafeFilename = filePaths.some(path => isUnsafeFilename(path))
|
|
420
429
|
if (hasUnsafeFilename) {
|
|
421
430
|
message.error(notSafeMsg)
|
|
422
431
|
return
|
|
423
432
|
}
|
|
424
433
|
|
|
434
|
+
if (isSshTerminal) {
|
|
435
|
+
this.setState({
|
|
436
|
+
dropFileModalVisible: true,
|
|
437
|
+
droppedFiles: filePaths.map(path => ({ path, isRemote: false }))
|
|
438
|
+
})
|
|
439
|
+
return
|
|
440
|
+
}
|
|
441
|
+
|
|
425
442
|
const filesAll = filePaths.map(path => `"${path}"`).join(' ')
|
|
426
443
|
this.attachAddon._sendData(filesAll)
|
|
427
444
|
}
|
|
428
445
|
}
|
|
429
446
|
|
|
447
|
+
handleDropFileModalCancel = () => {
|
|
448
|
+
this.setState({
|
|
449
|
+
dropFileModalVisible: false,
|
|
450
|
+
droppedFiles: []
|
|
451
|
+
})
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
handleDropFileAction = (action) => {
|
|
455
|
+
const { droppedFiles } = this.state
|
|
456
|
+
if (!droppedFiles || !droppedFiles.length) {
|
|
457
|
+
this.handleDropFileModalCancel()
|
|
458
|
+
return
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const filePaths = droppedFiles.map(f => f.path)
|
|
462
|
+
|
|
463
|
+
switch (action) {
|
|
464
|
+
case 'trzUpload': {
|
|
465
|
+
if (this.trzszClient && this.trzszClient.isActive) {
|
|
466
|
+
message.warning('A transfer is already in progress')
|
|
467
|
+
this.handleDropFileModalCancel()
|
|
468
|
+
return
|
|
469
|
+
}
|
|
470
|
+
window._apiControlSelectFile = filePaths
|
|
471
|
+
this.attachAddon._sendData('trz\r')
|
|
472
|
+
break
|
|
473
|
+
}
|
|
474
|
+
case 'rzUpload': {
|
|
475
|
+
if (this.zmodemClient && this.zmodemClient.isActive) {
|
|
476
|
+
message.warning('A transfer is already in progress')
|
|
477
|
+
this.handleDropFileModalCancel()
|
|
478
|
+
return
|
|
479
|
+
}
|
|
480
|
+
window._apiControlSelectFile = filePaths
|
|
481
|
+
this.attachAddon._sendData('rz\r')
|
|
482
|
+
break
|
|
483
|
+
}
|
|
484
|
+
case 'inputPath':
|
|
485
|
+
default: {
|
|
486
|
+
const filesAll = filePaths.map(path => `"${path}"`).join(' ')
|
|
487
|
+
this.attachAddon._sendData(filesAll)
|
|
488
|
+
break
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
this.handleDropFileModalCancel()
|
|
493
|
+
}
|
|
494
|
+
|
|
430
495
|
onSelection = () => {
|
|
431
496
|
if (
|
|
432
497
|
!this.props.config.copyWhenSelect ||
|
|
@@ -771,8 +836,35 @@ class Term extends Component {
|
|
|
771
836
|
}
|
|
772
837
|
}
|
|
773
838
|
|
|
839
|
+
onPasswordPromptDetected = () => {
|
|
840
|
+
if (!this.props.config.showCmdSuggestions) {
|
|
841
|
+
return
|
|
842
|
+
}
|
|
843
|
+
const cursorPos = this.getCursorPosition()
|
|
844
|
+
if (cursorPos) {
|
|
845
|
+
refsStatic
|
|
846
|
+
.get('terminal-suggestions')
|
|
847
|
+
?.openPasswordSuggestions(cursorPos)
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
onPasswordPromptCancelled = () => {
|
|
852
|
+
const suggestions = refsStatic.get('terminal-suggestions')
|
|
853
|
+
if (suggestions?.state?.passwordMode) {
|
|
854
|
+
suggestions.closeSuggestions()
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
774
858
|
onData = (d) => {
|
|
775
859
|
this.handleInputEvent(d)
|
|
860
|
+
// Skip normal suggestion logic when in password mode
|
|
861
|
+
const suggestions = refsStatic.get('terminal-suggestions')
|
|
862
|
+
if (suggestions?.state?.passwordMode) {
|
|
863
|
+
if (d === '\r' || d === '\n') {
|
|
864
|
+
this.closeSuggestions()
|
|
865
|
+
}
|
|
866
|
+
return
|
|
867
|
+
}
|
|
776
868
|
if (this.props.config.showCmdSuggestions) {
|
|
777
869
|
const data = this.getCurrentInput()
|
|
778
870
|
if (data && d !== '\r' && d !== '\n') {
|
|
@@ -1459,6 +1551,12 @@ class Term extends Component {
|
|
|
1459
1551
|
countdown={this.state.reconnectCountdown}
|
|
1460
1552
|
onCancel={this.handleCancelAutoReconnect}
|
|
1461
1553
|
/>
|
|
1554
|
+
<DropFileModal
|
|
1555
|
+
visible={this.state.dropFileModalVisible}
|
|
1556
|
+
files={this.state.droppedFiles}
|
|
1557
|
+
onSelect={this.handleDropFileAction}
|
|
1558
|
+
onCancel={this.handleDropFileModalCancel}
|
|
1559
|
+
/>
|
|
1462
1560
|
{spin}
|
|
1463
1561
|
</div>
|
|
1464
1562
|
</Dropdown>
|
|
@@ -127,6 +127,15 @@
|
|
|
127
127
|
&:hover
|
|
128
128
|
color var(--success)
|
|
129
129
|
|
|
130
|
+
.suggestion-hint
|
|
131
|
+
margin-left 5px
|
|
132
|
+
font-size 0.8em
|
|
133
|
+
color var(--text-light, #888)
|
|
134
|
+
white-space nowrap
|
|
135
|
+
overflow hidden
|
|
136
|
+
text-overflow ellipsis
|
|
137
|
+
max-width 150px
|
|
138
|
+
|
|
130
139
|
.suggestion-delete
|
|
131
140
|
margin-left 5px
|
|
132
141
|
visibility hidden
|
|
@@ -186,6 +186,7 @@ export default class VncSession extends PureComponent {
|
|
|
186
186
|
qualityLevel = 3, // 0-9, lower = faster performance
|
|
187
187
|
compressionLevel = 1, // 0-9, lower = faster performance
|
|
188
188
|
shared = true,
|
|
189
|
+
showDotCursor = true, // show dot cursor when server sends no cursor image (common on Windows)
|
|
189
190
|
username,
|
|
190
191
|
password
|
|
191
192
|
} = tab
|
|
@@ -376,6 +377,7 @@ export default class VncSession extends PureComponent {
|
|
|
376
377
|
rfb.qualityLevel = qualityLevel
|
|
377
378
|
rfb.compressionLevel = compressionLevel
|
|
378
379
|
rfb.viewOnly = viewOnly
|
|
380
|
+
rfb.showDotCursor = showDotCursor
|
|
379
381
|
this.rfb = rfb
|
|
380
382
|
}
|
|
381
383
|
|
|
@@ -49,6 +49,9 @@ export default function WidgetControl ({ formData, widgetInstancesLength }) {
|
|
|
49
49
|
config
|
|
50
50
|
}
|
|
51
51
|
window.store.widgetInstances.push(instance)
|
|
52
|
+
if (config.autoRun) {
|
|
53
|
+
window.store.toggleAutoRunWidget(instance)
|
|
54
|
+
}
|
|
52
55
|
showMsg(msg, 'success', result.serverInfo, 10)
|
|
53
56
|
} catch (err) {
|
|
54
57
|
console.error('Failed to run widget:', err)
|
|
@@ -1,12 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
Popconfirm,
|
|
3
|
+
Popover,
|
|
4
|
+
Tooltip,
|
|
5
|
+
Tag
|
|
6
|
+
} from 'antd'
|
|
7
|
+
import { CloseOutlined, CopyOutlined, ThunderboltOutlined } from '@ant-design/icons'
|
|
3
8
|
import { copy } from '../../common/clipboard'
|
|
9
|
+
import classnames from 'classnames'
|
|
10
|
+
import { auto } from 'manate/react'
|
|
4
11
|
|
|
5
12
|
const e = window.translate
|
|
6
13
|
|
|
7
|
-
export default function WidgetInstance ({ item }) {
|
|
8
|
-
const { id, title, serverInfo } = item
|
|
9
|
-
const cls = 'item-list-unit'
|
|
14
|
+
export default auto(function WidgetInstance ({ item }) {
|
|
15
|
+
const { id, title, serverInfo, autoRun } = item
|
|
16
|
+
const cls = classnames('item-list-unit', {
|
|
17
|
+
'autorun-active': autoRun
|
|
18
|
+
})
|
|
10
19
|
const delProps = {
|
|
11
20
|
title: e('del'),
|
|
12
21
|
className: 'pointer list-item-remove'
|
|
@@ -31,6 +40,9 @@ export default function WidgetInstance ({ item }) {
|
|
|
31
40
|
copy(serverInfo.url)
|
|
32
41
|
}
|
|
33
42
|
}
|
|
43
|
+
const handleToggleAutoRun = () => {
|
|
44
|
+
window.store.toggleAutoRunWidget(item)
|
|
45
|
+
}
|
|
34
46
|
const popoverContent = serverInfo
|
|
35
47
|
? (
|
|
36
48
|
<div>
|
|
@@ -45,12 +57,13 @@ export default function WidgetInstance ({ item }) {
|
|
|
45
57
|
</div>
|
|
46
58
|
)
|
|
47
59
|
: null
|
|
60
|
+
const tag = autoRun ? <Tag color='green'>{e('autoRun')}</Tag> : null
|
|
48
61
|
const titleDiv = (
|
|
49
62
|
<div
|
|
50
63
|
title={title}
|
|
51
64
|
className='elli pd1y pd2x list-item-title'
|
|
52
65
|
>
|
|
53
|
-
{title}
|
|
66
|
+
{tag} {title}
|
|
54
67
|
</div>
|
|
55
68
|
)
|
|
56
69
|
return (
|
|
@@ -71,6 +84,12 @@ export default function WidgetInstance ({ item }) {
|
|
|
71
84
|
)
|
|
72
85
|
: titleDiv
|
|
73
86
|
}
|
|
87
|
+
<Tooltip title='Toggle auto-run'>
|
|
88
|
+
<ThunderboltOutlined
|
|
89
|
+
className='pointer list-item-autorun'
|
|
90
|
+
onClick={handleToggleAutoRun}
|
|
91
|
+
/>
|
|
92
|
+
</Tooltip>
|
|
74
93
|
<Popconfirm
|
|
75
94
|
{...popProps}
|
|
76
95
|
>
|
|
@@ -78,4 +97,4 @@ export default function WidgetInstance ({ item }) {
|
|
|
78
97
|
</Popconfirm>
|
|
79
98
|
</div>
|
|
80
99
|
)
|
|
81
|
-
}
|
|
100
|
+
})
|
|
@@ -126,6 +126,7 @@ export default () => {
|
|
|
126
126
|
showModal: 0,
|
|
127
127
|
|
|
128
128
|
// setting sync related
|
|
129
|
+
autoSyncReady: false,
|
|
129
130
|
isSyncingSetting: false,
|
|
130
131
|
isSyncUpload: false,
|
|
131
132
|
isSyncDownload: false,
|
|
@@ -155,7 +156,7 @@ export default () => {
|
|
|
155
156
|
qmSortByFrequency: ls.getItem(qmSortByFrequencyKey) === 'yes',
|
|
156
157
|
|
|
157
158
|
// sidebar
|
|
158
|
-
openedSideBar: ls.getItem(openedSidebarKey),
|
|
159
|
+
openedSideBar: ls.getItem(openedSidebarKey) || '',
|
|
159
160
|
leftSidebarWidth: parseInt(ls.getItem(leftSidebarWidthKey), 10) || 300,
|
|
160
161
|
addPanelWidth: parseInt(ls.getItem(addPanelWidthLsKey), 10) || 300,
|
|
161
162
|
menuOpened: false,
|
|
@@ -200,6 +201,7 @@ export default () => {
|
|
|
200
201
|
// widgets
|
|
201
202
|
widgets: [],
|
|
202
203
|
widgetInstances: [],
|
|
204
|
+
autoRunWidgets: [],
|
|
203
205
|
// move item
|
|
204
206
|
openMoveModal: false,
|
|
205
207
|
moveItem: null,
|
|
@@ -206,9 +206,18 @@ export default (Store) => {
|
|
|
206
206
|
},
|
|
207
207
|
1000
|
|
208
208
|
)
|
|
209
|
+
setTimeout(
|
|
210
|
+
() => {
|
|
211
|
+
store.autoSyncReady = true
|
|
212
|
+
},
|
|
213
|
+
2000
|
|
214
|
+
)
|
|
209
215
|
if (store.config.checkUpdateOnStart) {
|
|
210
216
|
store.onCheckUpdate(false)
|
|
211
217
|
}
|
|
218
|
+
store.startAutoRunWidgets().catch(err => {
|
|
219
|
+
console.error('Failed to start autorun widgets:', err)
|
|
220
|
+
})
|
|
212
221
|
}
|
|
213
222
|
Store.prototype.initCommandLine = async function () {
|
|
214
223
|
const opts = await window.pre.runGlobalAsync('initCommandLine')
|
|
@@ -130,6 +130,14 @@ export default Store => {
|
|
|
130
130
|
result = await store.mcpSftpDownload(args)
|
|
131
131
|
break
|
|
132
132
|
|
|
133
|
+
// Transfer list/history operations
|
|
134
|
+
case 'sftp_transfer_list':
|
|
135
|
+
result = store.mcpSftpTransferList()
|
|
136
|
+
break
|
|
137
|
+
case 'sftp_transfer_history':
|
|
138
|
+
result = store.mcpSftpTransferHistory()
|
|
139
|
+
break
|
|
140
|
+
|
|
133
141
|
// Zmodem (trzsz/rzsz) operations
|
|
134
142
|
case 'zmodem_upload':
|
|
135
143
|
result = store.mcpZmodemUpload(args)
|
|
@@ -692,6 +700,16 @@ export default Store => {
|
|
|
692
700
|
}
|
|
693
701
|
}
|
|
694
702
|
|
|
703
|
+
// ==================== Transfer List/History APIs ====================
|
|
704
|
+
|
|
705
|
+
Store.prototype.mcpSftpTransferList = function () {
|
|
706
|
+
return deepCopy(window.store.fileTransfers)
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
Store.prototype.mcpSftpTransferHistory = function () {
|
|
710
|
+
return deepCopy(window.store.transferHistory)
|
|
711
|
+
}
|
|
712
|
+
|
|
695
713
|
// ==================== Zmodem (trzsz/rzsz) APIs ====================
|
|
696
714
|
|
|
697
715
|
Store.prototype.mcpZmodemUpload = function (args) {
|
package/client/store/sync.js
CHANGED
|
@@ -7,7 +7,7 @@ import copy from 'json-deep-copy'
|
|
|
7
7
|
import {
|
|
8
8
|
settingMap, packInfo, syncTypes, syncDataMaps
|
|
9
9
|
} from '../common/constants'
|
|
10
|
-
import {
|
|
10
|
+
import { update, getData } from '../common/db'
|
|
11
11
|
import fetch from '../common/fetch-from-server'
|
|
12
12
|
import download from '../common/download'
|
|
13
13
|
import { fixBookmarks } from '../common/db-fix'
|
|
@@ -152,10 +152,8 @@ export default (Store) => {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
Store.prototype.uploadSettingAll = async function () {
|
|
155
|
-
const { store, onSyncAll
|
|
156
|
-
|
|
157
|
-
if (syncCount < max) {
|
|
158
|
-
window.syncCount = syncCount + 1
|
|
155
|
+
const { store, onSyncAll } = window
|
|
156
|
+
if (store.autoSyncReady === false) {
|
|
159
157
|
return
|
|
160
158
|
}
|
|
161
159
|
if (onSyncAll) {
|
package/client/store/watch.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import createTitle from '../common/create-title'
|
|
6
6
|
import { autoRun } from 'manate'
|
|
7
|
-
import { update, remove, insert, dbNamesForWatch } from '../common/db'
|
|
7
|
+
import { update, remove, insert, dbNamesForWatch, dbNamesForSync } from '../common/db'
|
|
8
8
|
import {
|
|
9
9
|
sftpDefaultSortSettingKey,
|
|
10
10
|
checkedKeysLsKey,
|
|
@@ -68,7 +68,7 @@ export default store => {
|
|
|
68
68
|
)
|
|
69
69
|
}
|
|
70
70
|
await store.updateLastDataUpdateTime()
|
|
71
|
-
if (store.config.autoSync) {
|
|
71
|
+
if (store.config.autoSync && dbNamesForSync.includes(name)) {
|
|
72
72
|
await store.uploadSettingAll()
|
|
73
73
|
}
|
|
74
74
|
return store[name]
|
package/client/store/widgets.js
CHANGED
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
settingMap
|
|
8
8
|
} from '../common/constants'
|
|
9
9
|
import getInitItem from '../common/init-setting-item'
|
|
10
|
+
import deepCopy from 'json-deep-copy'
|
|
11
|
+
import generate from '../common/uid'
|
|
10
12
|
|
|
11
13
|
export default Store => {
|
|
12
14
|
Store.prototype.listWidgets = async () => {
|
|
@@ -58,4 +60,56 @@ export default Store => {
|
|
|
58
60
|
store.settingTab = settingMap.widgets
|
|
59
61
|
store.openSettingModal()
|
|
60
62
|
}
|
|
63
|
+
|
|
64
|
+
Store.prototype.toggleAutoRunWidget = (instance) => {
|
|
65
|
+
const { store } = window
|
|
66
|
+
const { widgetId, config } = instance
|
|
67
|
+
if (instance.autoRun) {
|
|
68
|
+
const index = store.autoRunWidgets.findIndex(
|
|
69
|
+
w => w.id === instance.autoRunId
|
|
70
|
+
)
|
|
71
|
+
if (index > -1) {
|
|
72
|
+
store.autoRunWidgets.splice(index, 1)
|
|
73
|
+
}
|
|
74
|
+
instance.autoRun = false
|
|
75
|
+
instance.autoRunId = undefined
|
|
76
|
+
} else {
|
|
77
|
+
const id = generate()
|
|
78
|
+
const item = {
|
|
79
|
+
id,
|
|
80
|
+
widgetId,
|
|
81
|
+
config
|
|
82
|
+
}
|
|
83
|
+
store.autoRunWidgets.push(item)
|
|
84
|
+
instance.autoRun = true
|
|
85
|
+
instance.autoRunId = id
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
Store.prototype.startAutoRunWidgets = async function () {
|
|
90
|
+
const { store } = window
|
|
91
|
+
const items = store.autoRunWidgets
|
|
92
|
+
if (!items || !items.length) {
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
for (const item of items) {
|
|
96
|
+
try {
|
|
97
|
+
const result = await store.runWidget(item.widgetId, deepCopy(item.config))
|
|
98
|
+
if (result && result.instanceId) {
|
|
99
|
+
const instance = {
|
|
100
|
+
id: result.instanceId,
|
|
101
|
+
title: `${result.widgetId} (${result.instanceId})`,
|
|
102
|
+
widgetId: result.widgetId,
|
|
103
|
+
serverInfo: result.serverInfo,
|
|
104
|
+
config: item.config,
|
|
105
|
+
autoRun: true,
|
|
106
|
+
autoRunId: item.id
|
|
107
|
+
}
|
|
108
|
+
store.widgetInstances.push(instance)
|
|
109
|
+
}
|
|
110
|
+
} catch (err) {
|
|
111
|
+
console.error(`Failed to autorun widget ${item.widgetId}:`, err)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
61
115
|
}
|