@electerm/electerm-react 1.51.21 → 1.60.16
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/constants.js +2 -0
- package/client/common/default-setting.js +12 -1
- package/client/components/ai/ai-chat-history-item.jsx +69 -0
- package/client/components/ai/ai-chat-history.jsx +31 -0
- package/client/components/ai/ai-chat.jsx +172 -0
- package/client/components/ai/ai-config.jsx +145 -0
- package/client/components/ai/ai-output.jsx +118 -0
- package/client/components/ai/ai.styl +70 -0
- package/client/components/ai/get-brand.js +34 -0
- package/client/components/ai/providers.js +14 -0
- package/client/components/bookmark-form/rdp-form-ui.jsx +1 -1
- package/client/components/footer/batch-input.jsx +13 -67
- package/client/components/footer/footer-entry.jsx +19 -3
- package/client/components/footer/footer.styl +4 -0
- package/client/components/footer/tab-select.jsx +9 -3
- package/client/components/layout/layout.jsx +5 -4
- package/client/components/main/main.jsx +20 -4
- package/client/components/shortcuts/shortcut-control.jsx +17 -2
- package/client/components/shortcuts/shortcut-handler.js +24 -8
- package/client/components/shortcuts/shortcuts-defaults.js +6 -0
- package/client/components/side-panel-r/right-side-panel.styl +6 -7
- package/client/components/side-panel-r/side-panel-r.jsx +32 -10
- package/client/components/sidebar/app-running-time.jsx +35 -0
- package/client/components/sidebar/history-item.jsx +20 -3
- package/client/components/sidebar/history.jsx +4 -1
- package/client/components/sidebar/info-modal.jsx +2 -0
- package/client/components/tabs/app-drag.jsx +1 -1
- package/client/components/tabs/index.jsx +16 -43
- package/client/components/tabs/no-session.jsx +40 -0
- package/client/components/tabs/tabs.styl +6 -0
- package/client/components/terminal/index.jsx +2 -2
- package/client/store/common.js +37 -2
- package/client/store/index.js +2 -290
- package/client/store/init-state.js +7 -1
- package/client/store/store.js +313 -0
- package/client/store/sync.js +4 -1
- package/client/store/tab.js +56 -2
- package/client/store/watch.js +9 -2
- package/package.json +1 -1
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* central state store powered by manate - https://github.com/tylerlong/manate
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import initState from './init-state'
|
|
6
|
+
import loadDataExtend from './load-data'
|
|
7
|
+
import dbUpgradeExtend from './db-upgrade'
|
|
8
|
+
import eventExtend from './event'
|
|
9
|
+
import syncExtend from './sync'
|
|
10
|
+
import appUpgradeExtend from './app-upgrade'
|
|
11
|
+
import bookmarkGroupExtend from './bookmark-group'
|
|
12
|
+
import bookmarkExtend from './bookmark'
|
|
13
|
+
import commonExtend from './common'
|
|
14
|
+
import contextMenuExtend from './context-menu'
|
|
15
|
+
import itemExtend from './item'
|
|
16
|
+
import quickCommandExtend from './quick-command'
|
|
17
|
+
import sessionExtend from './session'
|
|
18
|
+
import settingExtend from './setting'
|
|
19
|
+
import sidebarExtend from './sidebar'
|
|
20
|
+
import sysMenuExtend from './system-menu'
|
|
21
|
+
import tabExtend from './tab'
|
|
22
|
+
import uiThemeExtend from './ui-theme'
|
|
23
|
+
import terminalThemeExtend from './terminal-theme'
|
|
24
|
+
import transferHistoryExtend from './transfer-history'
|
|
25
|
+
import batchInputHistory from './batch-input-history'
|
|
26
|
+
import transferExtend from './transfer-list'
|
|
27
|
+
import addressBookmarkExtend from './address-bookmark'
|
|
28
|
+
import isColorDark from '../common/is-color-dark'
|
|
29
|
+
import { getReverseColor } from '../common/reverse-color'
|
|
30
|
+
import { uniq } from 'lodash-es'
|
|
31
|
+
import deepCopy from 'json-deep-copy'
|
|
32
|
+
import getBrand from '../components/ai/get-brand'
|
|
33
|
+
import {
|
|
34
|
+
settingMap,
|
|
35
|
+
paneMap,
|
|
36
|
+
settingSyncId,
|
|
37
|
+
settingShortcutsId,
|
|
38
|
+
settingTerminalId,
|
|
39
|
+
terminalSshConfigType
|
|
40
|
+
} from '../common/constants'
|
|
41
|
+
import getInitItem from '../common/init-setting-item'
|
|
42
|
+
import createTitle from '../common/create-title'
|
|
43
|
+
import {
|
|
44
|
+
theme
|
|
45
|
+
} from 'antd'
|
|
46
|
+
|
|
47
|
+
const e = window.translate
|
|
48
|
+
|
|
49
|
+
class Store {
|
|
50
|
+
constructor () {
|
|
51
|
+
Object.assign(
|
|
52
|
+
this,
|
|
53
|
+
initState()
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get width () {
|
|
58
|
+
return window.store.innerWidth
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get config () {
|
|
62
|
+
return deepCopy(window.store._config)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get currentQuickCommands () {
|
|
66
|
+
const { currentTab } = this
|
|
67
|
+
const { quickCommands } = window.store
|
|
68
|
+
const currentTabQuickCommands = (
|
|
69
|
+
currentTab.quickCommands || []
|
|
70
|
+
).map((d, i) => {
|
|
71
|
+
return {
|
|
72
|
+
...d,
|
|
73
|
+
id: 'tab-qm-' + currentTab.id + '#' + i
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
return [
|
|
77
|
+
...currentTabQuickCommands,
|
|
78
|
+
...quickCommands
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
get currentTab () {
|
|
83
|
+
const {
|
|
84
|
+
activeTabId
|
|
85
|
+
} = this
|
|
86
|
+
const { tabs } = window.store
|
|
87
|
+
const tab = tabs.find(t => t.id === activeTabId)
|
|
88
|
+
if (!tab) {
|
|
89
|
+
return false
|
|
90
|
+
}
|
|
91
|
+
return tab
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
get batchInputSelectedTabIds () {
|
|
95
|
+
return Array.from(window.store._batchInputSelectedTabIds)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
get rightPanelTitle () {
|
|
99
|
+
const {
|
|
100
|
+
rightPanelTab,
|
|
101
|
+
config: {
|
|
102
|
+
baseURLAI
|
|
103
|
+
}
|
|
104
|
+
} = window.store
|
|
105
|
+
if (rightPanelTab === 'ai') {
|
|
106
|
+
return getBrand(baseURLAI).brand || 'Custom AI Model'
|
|
107
|
+
}
|
|
108
|
+
return createTitle(window.store.currentTab)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
get inActiveTerminal () {
|
|
112
|
+
const { store } = window
|
|
113
|
+
if (store.showModal) {
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
const {
|
|
117
|
+
currentTab
|
|
118
|
+
} = store
|
|
119
|
+
if (!currentTab) {
|
|
120
|
+
return false
|
|
121
|
+
}
|
|
122
|
+
const {
|
|
123
|
+
type,
|
|
124
|
+
pane
|
|
125
|
+
} = currentTab
|
|
126
|
+
if (type === 'rdp' || type === 'vnc' || type === 'web') {
|
|
127
|
+
return false
|
|
128
|
+
}
|
|
129
|
+
return pane === paneMap.ssh ||
|
|
130
|
+
pane === paneMap.terminal
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
get quickCommandTags () {
|
|
134
|
+
const { quickCommands } = window.store
|
|
135
|
+
return uniq(
|
|
136
|
+
quickCommands.reduce((p, q) => {
|
|
137
|
+
return [
|
|
138
|
+
...p,
|
|
139
|
+
...(q.labels || [])
|
|
140
|
+
]
|
|
141
|
+
}, [])
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
get isTransporting () {
|
|
146
|
+
return window.store.tabs.some(t => t.isTransporting)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
get transferCount () {
|
|
150
|
+
return window.store.fileTransfers.length
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
get settingSidebarList () {
|
|
154
|
+
const {
|
|
155
|
+
settingTab
|
|
156
|
+
} = this
|
|
157
|
+
const arr = window.store.getSidebarList(settingTab)
|
|
158
|
+
const initItem = getInitItem(arr, settingTab)
|
|
159
|
+
return settingTab === settingMap.history
|
|
160
|
+
? arr
|
|
161
|
+
: [
|
|
162
|
+
deepCopy(initItem),
|
|
163
|
+
...arr
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
get termSearchOptions () {
|
|
168
|
+
const {
|
|
169
|
+
store
|
|
170
|
+
} = window
|
|
171
|
+
const theme = store.getThemeConfig()
|
|
172
|
+
return {
|
|
173
|
+
...window.store._termSearchOptions,
|
|
174
|
+
decorations: {
|
|
175
|
+
activeMatchBorder: theme.yellow,
|
|
176
|
+
activeMatchBackground: theme.selectionBackground,
|
|
177
|
+
activeMatchColorOverviewRuler: theme.selectionBackground,
|
|
178
|
+
matchBackground: theme.background,
|
|
179
|
+
matchOverviewRuler: theme.yellow,
|
|
180
|
+
matchBorder: getReverseColor(theme.background)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
get tabTitles () {
|
|
186
|
+
return window.store.tabs.map(d => d.title).join('#')
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
get setting () {
|
|
190
|
+
return [
|
|
191
|
+
{
|
|
192
|
+
id: settingTerminalId,
|
|
193
|
+
title: e('terminal')
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
id: settingShortcutsId,
|
|
197
|
+
title: e('settingShortcuts')
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
id: settingSyncId,
|
|
201
|
+
title: e('settingSync')
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
get onOperation () {
|
|
207
|
+
const {
|
|
208
|
+
store
|
|
209
|
+
} = window
|
|
210
|
+
return store.showModal ||
|
|
211
|
+
store.showInfoModal ||
|
|
212
|
+
store.showEditor ||
|
|
213
|
+
store.showFileModal
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
get uiThemeConfig () {
|
|
217
|
+
const { store } = window
|
|
218
|
+
const themeConf = store.getUiThemeConfig()
|
|
219
|
+
return {
|
|
220
|
+
token: {
|
|
221
|
+
borderRadius: 3,
|
|
222
|
+
colorPrimary: themeConf.primary,
|
|
223
|
+
colorBgBase: themeConf.main,
|
|
224
|
+
colorError: themeConf.error,
|
|
225
|
+
colorInfo: themeConf.info,
|
|
226
|
+
colorSuccess: themeConf.success,
|
|
227
|
+
colorWarning: themeConf.warn,
|
|
228
|
+
colorTextBase: themeConf.text,
|
|
229
|
+
colorLink: themeConf['text-light']
|
|
230
|
+
},
|
|
231
|
+
algorithm: isColorDark(themeConf.main) ? theme.darkAlgorithm : theme.defaultAlgorithm
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
get bookmarkTree () {
|
|
236
|
+
const {
|
|
237
|
+
bookmarks
|
|
238
|
+
} = window.store
|
|
239
|
+
return bookmarks.reduce((p, v) => {
|
|
240
|
+
return {
|
|
241
|
+
...p,
|
|
242
|
+
[v.id]: v
|
|
243
|
+
}
|
|
244
|
+
}, {})
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
hasSshConfig () {
|
|
248
|
+
return !!window.store
|
|
249
|
+
.bookmarkGroups
|
|
250
|
+
.find(b => b.id === terminalSshConfigType)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
get bookmarkGroupTree () {
|
|
254
|
+
const {
|
|
255
|
+
bookmarkGroups
|
|
256
|
+
} = window.store
|
|
257
|
+
return bookmarkGroups.reduce((p, v) => {
|
|
258
|
+
return {
|
|
259
|
+
...p,
|
|
260
|
+
[v.id]: v
|
|
261
|
+
}
|
|
262
|
+
}, {})
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
get hasOldConnectionHoppingBookmark () {
|
|
266
|
+
return window.store.bookmarks.some(b => {
|
|
267
|
+
return b.connectionHoppings?.length && !b.hasHopping
|
|
268
|
+
})
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const arrGetterProps = [
|
|
273
|
+
'addressBookmarks',
|
|
274
|
+
'addressBookmarksLocal',
|
|
275
|
+
'bookmarks',
|
|
276
|
+
'bookmarkGroups',
|
|
277
|
+
'profiles',
|
|
278
|
+
'quickCommands',
|
|
279
|
+
'terminalThemes'
|
|
280
|
+
]
|
|
281
|
+
|
|
282
|
+
for (const prop of arrGetterProps) {
|
|
283
|
+
Object.defineProperty(Store.prototype, prop, {
|
|
284
|
+
get: function () {
|
|
285
|
+
return JSON.parse(window.store[`_${prop}`] || '[]').filter(d => d)
|
|
286
|
+
}
|
|
287
|
+
})
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
loadDataExtend(Store)
|
|
291
|
+
eventExtend(Store)
|
|
292
|
+
dbUpgradeExtend(Store)
|
|
293
|
+
syncExtend(Store)
|
|
294
|
+
appUpgradeExtend(Store)
|
|
295
|
+
bookmarkGroupExtend(Store)
|
|
296
|
+
bookmarkExtend(Store)
|
|
297
|
+
commonExtend(Store)
|
|
298
|
+
contextMenuExtend(Store)
|
|
299
|
+
itemExtend(Store)
|
|
300
|
+
quickCommandExtend(Store)
|
|
301
|
+
sessionExtend(Store)
|
|
302
|
+
settingExtend(Store)
|
|
303
|
+
sidebarExtend(Store)
|
|
304
|
+
sysMenuExtend(Store)
|
|
305
|
+
tabExtend(Store)
|
|
306
|
+
terminalThemeExtend(Store)
|
|
307
|
+
uiThemeExtend(Store)
|
|
308
|
+
transferHistoryExtend(Store)
|
|
309
|
+
batchInputHistory(Store)
|
|
310
|
+
transferExtend(Store)
|
|
311
|
+
addressBookmarkExtend(Store)
|
|
312
|
+
|
|
313
|
+
export const StateStore = Store
|
package/client/store/sync.js
CHANGED
package/client/store/tab.js
CHANGED
|
@@ -341,7 +341,10 @@ export default Store => {
|
|
|
341
341
|
|
|
342
342
|
// Find the current tab index and its batch
|
|
343
343
|
const currentIndex = tabs.findIndex(t => t.id === activeTabId)
|
|
344
|
-
|
|
344
|
+
|
|
345
|
+
if (currentIndex === -1) {
|
|
346
|
+
return // Current tab not found, do nothing
|
|
347
|
+
}
|
|
345
348
|
|
|
346
349
|
const currentBatch = tabs[currentIndex].batch
|
|
347
350
|
|
|
@@ -363,6 +366,7 @@ export default Store => {
|
|
|
363
366
|
// If a valid next tab is found, update the activeTabId
|
|
364
367
|
if (nextIndex !== -1 && nextIndex !== currentIndex) {
|
|
365
368
|
store.activeTabId = tabs[nextIndex].id
|
|
369
|
+
store[`activeTabId${currentBatch}`] = tabs[nextIndex].id
|
|
366
370
|
}
|
|
367
371
|
}
|
|
368
372
|
|
|
@@ -455,7 +459,8 @@ export default Store => {
|
|
|
455
459
|
'srcId',
|
|
456
460
|
'status',
|
|
457
461
|
'pane',
|
|
458
|
-
'batch'
|
|
462
|
+
'batch',
|
|
463
|
+
'tabCount'
|
|
459
464
|
]
|
|
460
465
|
const { history } = store
|
|
461
466
|
const index = history.findIndex(d => {
|
|
@@ -492,4 +497,53 @@ export default Store => {
|
|
|
492
497
|
}
|
|
493
498
|
})()
|
|
494
499
|
}
|
|
500
|
+
|
|
501
|
+
Store.prototype.updateBatchInputSelectedTabIds = function () {
|
|
502
|
+
const { store } = window
|
|
503
|
+
store._batchInputSelectedTabIds = new Set([store.activeTabId])
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
Store.prototype.onSelectBatchInputSelectedTabId = action(function (id) {
|
|
507
|
+
const { store } = window
|
|
508
|
+
const { _batchInputSelectedTabIds } = store
|
|
509
|
+
if (_batchInputSelectedTabIds.has(id)) {
|
|
510
|
+
_batchInputSelectedTabIds.delete(id)
|
|
511
|
+
} else {
|
|
512
|
+
_batchInputSelectedTabIds.add(id)
|
|
513
|
+
}
|
|
514
|
+
if (_batchInputSelectedTabIds.size === 0) {
|
|
515
|
+
_batchInputSelectedTabIds.add(store.activeTabId)
|
|
516
|
+
}
|
|
517
|
+
})
|
|
518
|
+
|
|
519
|
+
Store.prototype.filterBatchInputSelectedTabIds = action(function () {
|
|
520
|
+
const { store } = window
|
|
521
|
+
const { _batchInputSelectedTabIds, tabs } = store
|
|
522
|
+
const validTabIds = new Set(tabs.map(tab => tab.id))
|
|
523
|
+
|
|
524
|
+
// Filter out invalid tab IDs
|
|
525
|
+
for (const id of _batchInputSelectedTabIds) {
|
|
526
|
+
if (!validTabIds.has(id)) {
|
|
527
|
+
_batchInputSelectedTabIds.delete(id)
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// If no valid tabs are selected, add the active tab
|
|
532
|
+
if (_batchInputSelectedTabIds.size === 0) {
|
|
533
|
+
_batchInputSelectedTabIds.add(store.activeTabId)
|
|
534
|
+
}
|
|
535
|
+
})
|
|
536
|
+
|
|
537
|
+
Store.prototype.selectAllBatchInputTabs = function () {
|
|
538
|
+
const { store } = window
|
|
539
|
+
const { tabs } = store
|
|
540
|
+
store._batchInputSelectedTabIds = new Set(tabs.map(tab => tab.id))
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
Store.prototype.selectNoneBatchInputTabs = action(function () {
|
|
544
|
+
const { store } = window
|
|
545
|
+
store._batchInputSelectedTabIds.clear()
|
|
546
|
+
// Ensure at least the active tab is selected
|
|
547
|
+
store._batchInputSelectedTabIds.add(store.activeTabId)
|
|
548
|
+
})
|
|
495
549
|
}
|
package/client/store/watch.js
CHANGED
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
checkedKeysLsKey,
|
|
11
11
|
expandedKeysLsKey,
|
|
12
12
|
resolutionsLsKey,
|
|
13
|
-
localAddrBookmarkLsKey
|
|
13
|
+
localAddrBookmarkLsKey,
|
|
14
|
+
aiChatHistoryKey
|
|
14
15
|
} from '../common/constants'
|
|
15
16
|
import * as ls from '../common/safe-local-storage'
|
|
16
17
|
import { debounce, isEmpty } from 'lodash-es'
|
|
@@ -103,6 +104,12 @@ export default store => {
|
|
|
103
104
|
}).start()
|
|
104
105
|
|
|
105
106
|
autoRun(() => {
|
|
107
|
+
ls.setItemJSON(aiChatHistoryKey, store.aiChatHistory)
|
|
108
|
+
return store.aiChatHistory
|
|
109
|
+
}).start()
|
|
110
|
+
|
|
111
|
+
autoRun(() => {
|
|
112
|
+
store.updateBatchInputSelectedTabIds()
|
|
106
113
|
const tabs = store.getTabs()
|
|
107
114
|
const { activeTabId } = store
|
|
108
115
|
const tab = tabs.find(t => t.id === activeTabId)
|
|
@@ -112,7 +119,7 @@ export default store => {
|
|
|
112
119
|
window.store.currentLayoutBatch = tab.batch
|
|
113
120
|
}
|
|
114
121
|
if (tab && store.rightPanelVisible) {
|
|
115
|
-
window.store.
|
|
122
|
+
window.store.openInfoPanelAction()
|
|
116
123
|
}
|
|
117
124
|
return store.activeTabId
|
|
118
125
|
}).start()
|