@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.
Files changed (39) hide show
  1. package/client/common/constants.js +2 -0
  2. package/client/common/default-setting.js +12 -1
  3. package/client/components/ai/ai-chat-history-item.jsx +69 -0
  4. package/client/components/ai/ai-chat-history.jsx +31 -0
  5. package/client/components/ai/ai-chat.jsx +172 -0
  6. package/client/components/ai/ai-config.jsx +145 -0
  7. package/client/components/ai/ai-output.jsx +118 -0
  8. package/client/components/ai/ai.styl +70 -0
  9. package/client/components/ai/get-brand.js +34 -0
  10. package/client/components/ai/providers.js +14 -0
  11. package/client/components/bookmark-form/rdp-form-ui.jsx +1 -1
  12. package/client/components/footer/batch-input.jsx +13 -67
  13. package/client/components/footer/footer-entry.jsx +19 -3
  14. package/client/components/footer/footer.styl +4 -0
  15. package/client/components/footer/tab-select.jsx +9 -3
  16. package/client/components/layout/layout.jsx +5 -4
  17. package/client/components/main/main.jsx +20 -4
  18. package/client/components/shortcuts/shortcut-control.jsx +17 -2
  19. package/client/components/shortcuts/shortcut-handler.js +24 -8
  20. package/client/components/shortcuts/shortcuts-defaults.js +6 -0
  21. package/client/components/side-panel-r/right-side-panel.styl +6 -7
  22. package/client/components/side-panel-r/side-panel-r.jsx +32 -10
  23. package/client/components/sidebar/app-running-time.jsx +35 -0
  24. package/client/components/sidebar/history-item.jsx +20 -3
  25. package/client/components/sidebar/history.jsx +4 -1
  26. package/client/components/sidebar/info-modal.jsx +2 -0
  27. package/client/components/tabs/app-drag.jsx +1 -1
  28. package/client/components/tabs/index.jsx +16 -43
  29. package/client/components/tabs/no-session.jsx +40 -0
  30. package/client/components/tabs/tabs.styl +6 -0
  31. package/client/components/terminal/index.jsx +2 -2
  32. package/client/store/common.js +37 -2
  33. package/client/store/index.js +2 -290
  34. package/client/store/init-state.js +7 -1
  35. package/client/store/store.js +313 -0
  36. package/client/store/sync.js +4 -1
  37. package/client/store/tab.js +56 -2
  38. package/client/store/watch.js +9 -2
  39. 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
@@ -492,7 +492,10 @@ export default (Store) => {
492
492
  'language',
493
493
  'copyWhenSelect',
494
494
  'customCss',
495
- 'dataSyncSelected'
495
+ 'dataSyncSelected',
496
+ 'baseURLAI',
497
+ 'modelAI',
498
+ 'roleAI'
496
499
  ]
497
500
  return pick(store.config, configSyncKeys)
498
501
  }
@@ -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
- if (currentIndex === -1) return // Current tab not found, do nothing
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
  }
@@ -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.openInfoPanel()
122
+ window.store.openInfoPanelAction()
116
123
  }
117
124
  return store.activeTabId
118
125
  }).start()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "1.51.21",
3
+ "version": "1.60.16",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",