@electerm/electerm-react 1.39.88 → 1.39.103

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 (104) hide show
  1. package/client/common/constants.js +6 -3
  2. package/client/common/create-title.jsx +2 -3
  3. package/client/common/init-setting-item.js +3 -6
  4. package/client/common/new-terminal.js +1 -2
  5. package/client/common/terminal-theme.js +2 -3
  6. package/client/components/auth/login.jsx +8 -3
  7. package/client/components/auth/login.styl +7 -1
  8. package/client/components/batch-op/batch-op.jsx +18 -36
  9. package/client/components/bookmark-form/form-ssh-common.jsx +6 -9
  10. package/client/components/bookmark-form/form-tabs.jsx +4 -8
  11. package/client/components/bookmark-form/index.jsx +5 -9
  12. package/client/components/bookmark-form/local-form-ui.jsx +4 -7
  13. package/client/components/bookmark-form/proxy.jsx +1 -2
  14. package/client/components/bookmark-form/quick-command.jsx +7 -8
  15. package/client/components/bookmark-form/rdp-form-ui.jsx +3 -5
  16. package/client/components/bookmark-form/render-auth-ssh.jsx +2 -3
  17. package/client/components/bookmark-form/render-connection-hopping.jsx +9 -11
  18. package/client/components/bookmark-form/render-delayed-scripts.jsx +2 -3
  19. package/client/components/bookmark-form/render-ssh-tunnel.jsx +9 -12
  20. package/client/components/bookmark-form/serial-form-ui.jsx +5 -9
  21. package/client/components/bookmark-form/sftp-enable.jsx +1 -2
  22. package/client/components/bookmark-form/telnet-form-ui.jsx +2 -4
  23. package/client/components/bookmark-form/tree-delete.jsx +3 -4
  24. package/client/components/bookmark-form/use-quick-commands.jsx +5 -6
  25. package/client/components/bookmark-form/use-submit.jsx +1 -2
  26. package/client/components/bookmark-form/use-ui.jsx +4 -6
  27. package/client/components/bookmark-form/vnc-form-ui.jsx +3 -5
  28. package/client/components/bookmark-form/web-form-ui.jsx +3 -5
  29. package/client/components/common/markdown.jsx +1 -1
  30. package/client/components/context-menu/context-menu.jsx +3 -4
  31. package/client/components/context-menu/menu-btn.jsx +13 -18
  32. package/client/components/footer/batch-input.jsx +2 -3
  33. package/client/components/footer/footer-entry.jsx +2 -3
  34. package/client/components/main/error-wrapper.jsx +2 -4
  35. package/client/components/main/upgrade.jsx +2 -4
  36. package/client/components/main/upgrade.styl +4 -1
  37. package/client/components/profile/profile-form-elem.jsx +28 -10
  38. package/client/components/quick-commands/quick-commands-box.jsx +1 -2
  39. package/client/components/quick-commands/quick-commands-form-elem.jsx +7 -12
  40. package/client/components/quick-commands/quick-commands-list-form.jsx +6 -7
  41. package/client/components/quick-commands/quick-commands-list.jsx +2 -3
  42. package/client/components/quick-commands/quick-commands-select.jsx +1 -2
  43. package/client/components/rdp/rdp-session.jsx +0 -3
  44. package/client/components/rdp/resolution-form.jsx +3 -6
  45. package/client/components/session/session.jsx +17 -6
  46. package/client/components/session/session.styl +5 -1
  47. package/client/components/session/sessions.jsx +4 -6
  48. package/client/components/setting-panel/keywords-form.jsx +2 -3
  49. package/client/components/setting-panel/list.jsx +3 -6
  50. package/client/components/setting-panel/setting-common.jsx +10 -14
  51. package/client/components/setting-panel/setting-modal.jsx +7 -11
  52. package/client/components/setting-panel/setting-terminal.jsx +13 -16
  53. package/client/components/setting-panel/start-session-select.jsx +1 -2
  54. package/client/components/setting-panel/tab-history.jsx +2 -3
  55. package/client/components/setting-sync/data-import.jsx +4 -7
  56. package/client/components/setting-sync/data-select.jsx +4 -16
  57. package/client/components/setting-sync/setting-sync-form.jsx +71 -48
  58. package/client/components/sftp/address-bar.jsx +1 -2
  59. package/client/components/sftp/confirm-modal-store.jsx +1 -2
  60. package/client/components/sftp/file-item.jsx +6 -8
  61. package/client/components/sftp/file-mode-modal.jsx +1 -2
  62. package/client/components/sftp/file-props-modal.jsx +1 -2
  63. package/client/components/sftp/list-table-ui.jsx +1 -2
  64. package/client/components/sftp/permission-render.jsx +1 -2
  65. package/client/components/sftp/sftp-entry.jsx +21 -7
  66. package/client/components/sftp/transfer-tag.jsx +1 -2
  67. package/client/components/shortcuts/shortcuts.jsx +5 -28
  68. package/client/components/sidebar/bookmark.jsx +6 -9
  69. package/client/components/sidebar/history.jsx +4 -6
  70. package/client/components/sidebar/index.jsx +9 -16
  71. package/client/components/sidebar/info-modal.jsx +10 -15
  72. package/client/components/sidebar/transfer-history-modal.jsx +3 -6
  73. package/client/components/sidebar/transfer-list-control.jsx +1 -2
  74. package/client/components/sidebar/transfer-list.jsx +1 -2
  75. package/client/components/sidebar/transfer-modal.jsx +2 -4
  76. package/client/components/sidebar/transport-ui.jsx +1 -2
  77. package/client/components/tabs/index.jsx +32 -22
  78. package/client/components/tabs/tab.jsx +5 -9
  79. package/client/components/tabs/window-control.jsx +4 -5
  80. package/client/components/terminal/index.jsx +5 -7
  81. package/client/components/terminal/term-search.jsx +2 -3
  82. package/client/components/terminal/terminal-interactive.jsx +2 -4
  83. package/client/components/terminal-info/activity.jsx +4 -5
  84. package/client/components/terminal-info/base.jsx +3 -4
  85. package/client/components/terminal-info/terminal-info.styl +1 -0
  86. package/client/components/terminal-theme/index.jsx +6 -9
  87. package/client/components/terminal-theme/theme-list.jsx +1 -2
  88. package/client/components/text-editor/text-editor-form.jsx +4 -8
  89. package/client/components/text-editor/text-editor.jsx +2 -3
  90. package/client/components/tree-list/bookmark-transport.jsx +4 -7
  91. package/client/components/tree-list/tree-list-item.jsx +4 -7
  92. package/client/components/tree-list/tree-list.jsx +3 -6
  93. package/client/components/vnc/vnc-form.jsx +2 -4
  94. package/client/components/vnc/vnc-session.jsx +1 -2
  95. package/client/entry/basic.js +4 -6
  96. package/client/store/common.js +10 -12
  97. package/client/store/index.js +4 -7
  98. package/client/store/init-state.js +2 -3
  99. package/client/store/load-data.js +10 -0
  100. package/client/store/setting.js +32 -5
  101. package/client/store/sync.js +10 -6
  102. package/client/store/system-menu.js +4 -6
  103. package/client/store/terminal-theme.js +2 -4
  104. package/package.json +1 -1
@@ -15,10 +15,7 @@ import copy from 'json-deep-copy'
15
15
  import { find, uniq, isEqual } from 'lodash-es'
16
16
  import { fixBookmarks } from '../../common/db-fix'
17
17
 
18
- const { prefix } = window
19
- const f = prefix('form')
20
- const t = prefix('terminalThemes')
21
- const m = prefix('menu')
18
+ const e = window.translate
22
19
 
23
20
  export default class BookmarkTransport extends Component {
24
21
  beforeUpload = async (file) => {
@@ -118,7 +115,7 @@ export default class BookmarkTransport extends Component {
118
115
  <Button
119
116
  icon={<EditOutlined />}
120
117
  onClick={this.handleToggleEdit}
121
- title={m('edit')}
118
+ title={e('edit')}
122
119
  key='edit-and-del'
123
120
  />
124
121
  )
@@ -130,7 +127,7 @@ export default class BookmarkTransport extends Component {
130
127
  <Button
131
128
  icon={<DownloadOutlined />}
132
129
  onClick={this.handleDownload}
133
- title={t('export')}
130
+ title={e('export')}
134
131
  key='export'
135
132
  />,
136
133
  <Upload
@@ -140,7 +137,7 @@ export default class BookmarkTransport extends Component {
140
137
  >
141
138
  <Button
142
139
  icon={<UploadOutlined />}
143
- title={f('importFromFile')}
140
+ title={e('importFromFile')}
144
141
  />
145
142
  </Upload>
146
143
  ]
@@ -24,10 +24,7 @@ import uid from '../../common/uid'
24
24
  import { memo } from 'react'
25
25
  import './tree-list.styl'
26
26
 
27
- const { prefix } = window
28
- const e = prefix('menu')
29
- const c = prefix('common')
30
- const s = prefix('setting')
27
+ const e = window.translate
31
28
 
32
29
  export default memo(function TreeListItem (props) {
33
30
  const handleDel = (e) => {
@@ -43,7 +40,7 @@ export default memo(function TreeListItem (props) {
43
40
  title={e('del') + '?'}
44
41
  onConfirm={handleDel}
45
42
  okText={e('del')}
46
- cancelText={c('cancel')}
43
+ cancelText={e('cancel')}
47
44
  placement='top'
48
45
  >
49
46
  <CloseOutlined title={e('del')} className='pointer tree-control-btn' />
@@ -86,7 +83,7 @@ export default memo(function TreeListItem (props) {
86
83
  return (
87
84
  <FolderAddOutlined
88
85
  key='new-tree'
89
- title={`${s('new')} ${c('bookmarkCategory')}`}
86
+ title={`${e('new')} ${e('bookmarkCategory')}`}
90
87
  onClick={handleAddSubCat}
91
88
  className='pointer tree-control-btn'
92
89
  />
@@ -129,7 +126,7 @@ export default memo(function TreeListItem (props) {
129
126
  return null
130
127
  }
131
128
  return (
132
- <Tooltip title={s('openAll')}>
129
+ <Tooltip title={e('openAll')}>
133
130
  <FolderOpenOutlined
134
131
  key='open-all-tree'
135
132
  onClick={handleOpenAll}
@@ -42,10 +42,7 @@ import './tree-list.styl'
42
42
  import TreeExpander from './tree-expander'
43
43
  import TreeListItem from './tree-list-item'
44
44
 
45
- const { prefix } = window
46
- const e = prefix('menu')
47
- const c = prefix('common')
48
- const s = prefix('setting')
45
+ const e = window.translate
49
46
 
50
47
  export default class ItemListTree extends Component {
51
48
  constructor (props) {
@@ -902,13 +899,13 @@ export default class ItemListTree extends Component {
902
899
  <Space.Compact>
903
900
  <Button
904
901
  onClick={this.handleNewBookmark}
905
- title={`${s('new')} ${c('bookmarks')}`}
902
+ title={`${e('new')} ${e('bookmarks')}`}
906
903
  >
907
904
  <BookOutlined className='with-plus' />
908
905
  </Button>
909
906
  <Button
910
907
  onClick={this.handleNewBookmarkGroup}
911
- title={`${s('new')} ${c('bookmarkCategory')}`}
908
+ title={`${e('new')} ${e('bookmarkCategory')}`}
912
909
  >
913
910
  <FolderOutlined className='with-plus' />
914
911
  </Button>
@@ -10,9 +10,7 @@ import {
10
10
  import { formItemLayout, tailFormItemLayout } from '../../common/form-layout'
11
11
 
12
12
  const FormItem = Form.Item
13
- const { prefix } = window
14
- const e = prefix('form')
15
- const s = prefix('sftp')
13
+ const e = window.translate
16
14
 
17
15
  export default function VncForm (props) {
18
16
  const [form] = Form.useForm()
@@ -57,7 +55,7 @@ export default function VncForm (props) {
57
55
  type='primary'
58
56
  htmlType='submit'
59
57
  >
60
- {s('submit')}
58
+ {e('submit')}
61
59
  </Button>
62
60
  </FormItem>
63
61
  </div>
@@ -18,8 +18,7 @@ import resolutions from '../rdp/resolutions'
18
18
  import RFB from '@novnc/novnc/core/rfb'
19
19
  import VncForm from './vnc-form'
20
20
 
21
- const { prefix } = window
22
- const e = prefix('form')
21
+ const e = window.translate
23
22
 
24
23
  export default class VncSession extends RdpSession {
25
24
  constructor (props) {
@@ -43,12 +43,10 @@ async function load () {
43
43
  window.getLang = (lang = window.store?.config.language || 'en_us') => {
44
44
  return _get(window.langMap, `[${lang}].lang`)
45
45
  }
46
- window.prefix = prefix => {
47
- return (id) => {
48
- const lang = window.getLang()
49
- const str = _get(lang, `[${prefix}][${id}]`) || id
50
- return window.capitalizeFirstLetter(str)
51
- }
46
+ window.translate = txt => {
47
+ const lang = window.getLang()
48
+ const str = _get(lang, `[${txt}]`) || txt
49
+ return window.capitalizeFirstLetter(str)
52
50
  }
53
51
  await loadWorker()
54
52
  loadScript()
@@ -16,9 +16,7 @@ import {
16
16
  } from '../common/constants'
17
17
  import * as ls from '../common/safe-local-storage'
18
18
 
19
- const { prefix } = window
20
- const m = prefix('menu')
21
- const c = prefix('common')
19
+ const e = window.translate
22
20
 
23
21
  export default Store => {
24
22
  Store.prototype.storeAssign = function (updates) {
@@ -160,14 +158,14 @@ export default Store => {
160
158
  ls.setItem(dismissDelKeyTipLsKey, 'y')
161
159
  window.store.hideDelKeyTip = true
162
160
  }
163
- Store.prototype.beforeExit = function (e) {
161
+ Store.prototype.beforeExit = function (evt) {
164
162
  const { confirmBeforeExit } = window.store.config
165
163
  if (
166
164
  (confirmBeforeExit &&
167
165
  !window.confirmExit) ||
168
166
  window.store.isTransporting
169
167
  ) {
170
- e.returnValue = false
168
+ evt.returnValue = false
171
169
  let mod = null
172
170
  mod = Modal.confirm({
173
171
  onCancel: () => {
@@ -178,14 +176,14 @@ export default Store => {
178
176
  window.confirmExit = true
179
177
  window.store[window.exitFunction]()
180
178
  },
181
- title: m('quit'),
182
- okText: c('ok'),
183
- cancelText: c('cancel'),
179
+ title: e('quit'),
180
+ okText: e('ok'),
181
+ cancelText: e('cancel'),
184
182
  content: ''
185
183
  })
186
184
  }
187
185
  }
188
- Store.prototype.beforeExitApp = function (e, name) {
186
+ Store.prototype.beforeExitApp = function (evt, name) {
189
187
  let mod = null
190
188
  mod = Modal.confirm({
191
189
  onCancel: () => {
@@ -195,9 +193,9 @@ export default Store => {
195
193
  onOk: () => {
196
194
  window.pre.runGlobalAsync(name)
197
195
  },
198
- title: m('quit'),
199
- okText: c('ok'),
200
- cancelText: c('cancel'),
196
+ title: e('quit'),
197
+ okText: e('ok'),
198
+ cancelText: e('cancel'),
201
199
  content: ''
202
200
  })
203
201
  }
@@ -41,10 +41,7 @@ import {
41
41
  theme
42
42
  } from 'antd'
43
43
 
44
- const { prefix } = window
45
- const ss = prefix('settingSync')
46
- const s = prefix('setting')
47
- const sss = prefix('ssh')
44
+ const e = window.translate
48
45
 
49
46
  function getReverseColor (hex) {
50
47
  // Check if the input is a valid hex color code
@@ -201,15 +198,15 @@ class Store {
201
198
  return [
202
199
  {
203
200
  id: settingTerminalId,
204
- title: sss('terminal')
201
+ title: e('terminal')
205
202
  },
206
203
  {
207
204
  id: settingShortcutsId,
208
- title: s('settingShortcuts')
205
+ title: e('settingShortcuts')
209
206
  },
210
207
  {
211
208
  id: settingSyncId,
212
- title: ss('settingSync')
209
+ title: e('settingSync')
213
210
  }
214
211
  ]
215
212
  }
@@ -25,13 +25,12 @@ import { buildDefaultThemes } from '../common/terminal-theme'
25
25
  import * as ls from '../common/safe-local-storage'
26
26
  import initSettingItem from '../common/init-setting-item'
27
27
 
28
- const { prefix } = window
29
- const t = prefix('terminalThemes')
28
+ const e = window.translate
30
29
 
31
30
  function getDefaultBookmarkGroups (bookmarks) {
32
31
  return [
33
32
  JSON.stringify({
34
- title: t(defaultBookmarkGroupId),
33
+ title: e(defaultBookmarkGroupId),
35
34
  id: defaultBookmarkGroupId,
36
35
  bookmarkIds: bookmarks.map(d => d.id)
37
36
  })
@@ -11,6 +11,7 @@ import defaultSettings from '../common/default-setting'
11
11
  import encodes from '../components/bookmark-form/encodes'
12
12
  import runIdle from '../common/run-idle'
13
13
  import { initWsCommon } from '../common/fetch-from-server'
14
+ import safeParse from '../common/parse-json-safe'
14
15
 
15
16
  function getHost (argv, opts) {
16
17
  const arr = argv
@@ -75,6 +76,15 @@ export async function addTabFromCommandLine (store, opts) {
75
76
  if (options.port && parseInt10(options.port)) {
76
77
  update.port = parseInt10(options.port)
77
78
  }
79
+ if (options.opts) {
80
+ const opts = safeParse(options.opts)
81
+ if (opts !== options.opts) {
82
+ Object.assign(update, opts)
83
+ }
84
+ }
85
+ if (options.type) {
86
+ update.type = options.type
87
+ }
78
88
  Object.assign(conf, update)
79
89
  if (options.privateKeyPath) {
80
90
  conf.privateKey = await fs.readFile(options.privateKeyPath)
@@ -18,8 +18,7 @@ import { buildNewTheme } from '../common/terminal-theme'
18
18
  import getInitItem from '../common/init-setting-item'
19
19
  import newTerm from '../common/new-terminal'
20
20
 
21
- const { prefix } = window
22
- const m = prefix('menu')
21
+ const e = window.translate
23
22
 
24
23
  export default Store => {
25
24
  Store.prototype.setConfig = function (conf) {
@@ -95,17 +94,45 @@ export default Store => {
95
94
  if (!item) {
96
95
  return
97
96
  }
97
+
98
98
  store.addTab({
99
99
  ...item,
100
100
  from: 'bookmarks',
101
101
  srcId: item.id,
102
102
  ...newTerm(true, true)
103
103
  })
104
- item.id = generate()
104
+
105
105
  if (store.config.disableSshHistory) {
106
106
  return
107
107
  }
108
- history.unshift(item)
108
+
109
+ // Critical Change: Use bookmarkId for matching instead of history id
110
+ const bookmarkId = item.id
111
+ const existingIndex = history.findIndex(h => h.bookmarkId === bookmarkId)
112
+ if (existingIndex >= 0) {
113
+ history[existingIndex].count = (history[existingIndex].count || 0) + 1
114
+ history[existingIndex].lastUse = Date.now()
115
+ const updatedItem = history.splice(existingIndex, 1)[0]
116
+ history.unshift(updatedItem)
117
+ } else {
118
+ const historyItem = {
119
+ ...item,
120
+ id: generate(), // History item gets a unique id
121
+ bookmarkId, // Store original bookmark id for future matching
122
+ count: 1,
123
+ lastUse: Date.now()
124
+ }
125
+ history.unshift(historyItem)
126
+ }
127
+
128
+ history.sort((a, b) => b.count - a.count || b.lastUse - a.lastUse)
129
+
130
+ // Optional: Consider max history length
131
+ const maxHistoryLength = store.config.maxHistoryLength || 50
132
+ if (history.length > maxHistoryLength) {
133
+ history.length = maxHistoryLength
134
+ }
135
+
109
136
  store.setItems('history', history)
110
137
  }
111
138
 
@@ -161,7 +188,7 @@ export default Store => {
161
188
  const { store } = window
162
189
  if (store.isSencondInstance) {
163
190
  return message.warning(
164
- m('sencondInstanceTip')
191
+ e('sencondInstanceTip')
165
192
  )
166
193
  }
167
194
  store.showModal = modals.setting
@@ -50,8 +50,12 @@ export default (Store) => {
50
50
  }
51
51
 
52
52
  Store.prototype.getSyncToken = function (type) {
53
- if (type === syncTypes.custom) {
54
- return ['AccessToken', 'ApiUrl', 'GistId'].map(
53
+ if (type === syncTypes.custom || type === syncTypes.cloud) {
54
+ const arr = ['AccessToken', 'ApiUrl']
55
+ if (type === syncTypes.custom) {
56
+ arr.push('GistId')
57
+ }
58
+ return arr.map(
55
59
  p => {
56
60
  return get(window.store.config, 'syncSetting.' + type + p)
57
61
  }
@@ -149,11 +153,11 @@ export default (Store) => {
149
153
  store.isSyncUpload = true
150
154
  const token = store.getSyncToken(type)
151
155
  let gistId = store.getSyncGistId(type)
152
- if (!gistId) {
156
+ if (!gistId && type !== syncTypes.cloud && type !== syncTypes.custom) {
153
157
  await store.createGist(type)
154
158
  gistId = store.getSyncGistId(type)
155
159
  }
156
- if (!gistId) {
160
+ if (!gistId && type !== syncTypes.custom && type !== syncTypes.cloud) {
157
161
  window.isSyncing = false
158
162
  store.isSyncingSetting = false
159
163
  store.isSyncUpload = false
@@ -218,11 +222,11 @@ export default (Store) => {
218
222
  store.isSyncDownload = true
219
223
  const token = store.getSyncToken(type)
220
224
  let gistId = store.getSyncGistId(type)
221
- if (!gistId) {
225
+ if (!gistId && type !== syncTypes.cloud && type !== syncTypes.custom) {
222
226
  await store.createGist(type)
223
227
  gistId = store.getSyncGistId(type)
224
228
  }
225
- if (!gistId) {
229
+ if (!gistId && type !== syncTypes.custom && type !== syncTypes.cloud) {
226
230
  return
227
231
  }
228
232
  const pass = store.getSyncPassword(type)
@@ -11,9 +11,7 @@ import {
11
11
  minZoom
12
12
  } from '../common/constants'
13
13
 
14
- const { prefix } = window
15
- const m = prefix('menu')
16
- const c = prefix('common')
14
+ const e = window.translate
17
15
 
18
16
  export default Store => {
19
17
  Store.prototype.zoom = function (level = 1, plus = false, zoomOnly) {
@@ -83,9 +81,9 @@ export default Store => {
83
81
  mod = Modal.confirm({
84
82
  onCancel: () => mod.destroy(),
85
83
  onOk: store.doExit,
86
- title: m('quit'),
87
- okText: c('ok'),
88
- cancelText: c('cancel'),
84
+ title: e('quit'),
85
+ okText: e('ok'),
86
+ cancelText: e('cancel'),
89
87
  content: ''
90
88
  })
91
89
  }
@@ -12,9 +12,7 @@ import {
12
12
  import copy from 'json-deep-copy'
13
13
  import { convertTheme } from '../common/terminal-theme'
14
14
 
15
- const { terminalThemes } = settingMap
16
- const { prefix } = window
17
- const t = prefix(terminalThemes)
15
+ const e = window.translate
18
16
 
19
17
  export default Store => {
20
18
  Store.prototype.getTerminalThemes = function () {
@@ -105,7 +103,7 @@ export default Store => {
105
103
  }
106
104
  )
107
105
  message.info(
108
- `${t('default')} ${t('themeConfig')} ${t('updated')}`
106
+ `${e('default')} ${e('themeConfig')} ${e('updated')}`
109
107
  )
110
108
  }
111
109
  const hasLightTheme = find(store.getTerminalThemes(), d => d.id === defaultThemeLight.id)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "1.39.88",
3
+ "version": "1.39.103",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",