@electerm/electerm-react 1.50.31 → 1.50.46

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.
@@ -48,7 +48,6 @@ export default class CssOverwrite extends PureComponent {
48
48
 
49
49
  const styles = [
50
50
  `background-image: ${st}`,
51
- 'background-size: cover',
52
51
  'background-position: center'
53
52
  ]
54
53
 
@@ -23,20 +23,30 @@ import { isMac, isWin } from '../../common/constants'
23
23
  import TermFullscreenControl from './term-fullscreen-control'
24
24
  import TerminalInfo from '../terminal-info/terminal-info'
25
25
  import { LoadingUI } from './loading'
26
- import { ConfigProvider, notification } from 'antd'
26
+ import { ConfigProvider, notification, message } from 'antd'
27
27
  import InfoModal from '../sidebar/info-modal.jsx'
28
28
  import RightSidePanel from '../side-panel-r/side-panel-r'
29
29
  import { pick } from 'lodash-es'
30
30
  import './wrapper.styl'
31
31
 
32
+ function setupGlobalMessageDismiss () {
33
+ document.addEventListener('click', (event) => {
34
+ const messageElement = event.target.closest('.ant-message-notice')
35
+ if (messageElement) {
36
+ message.destroy()
37
+ }
38
+ })
39
+ }
40
+
32
41
  export default auto(function Index (props) {
33
42
  useEffect(() => {
34
43
  notification.config({
35
44
  placement: 'bottomRight'
36
45
  })
46
+ setupGlobalMessageDismiss()
37
47
  const { store } = props
38
48
  window.addEventListener('resize', store.onResize)
39
- store.onResize()
49
+ setTimeout(store.triggerResize, 200)
40
50
  store.initStoreEvents()
41
51
  const { ipcOnEvent } = window.pre
42
52
  ipcOnEvent('checkupdate', store.onCheckUpdate)
@@ -119,7 +119,7 @@ class Sessions extends Component {
119
119
  currentTabId: id
120
120
  })
121
121
  } else {
122
- document.querySelector('.tab.active').click()
122
+ document.querySelector('.tab.active')?.click()
123
123
  }
124
124
  }
125
125
 
@@ -138,17 +138,15 @@ class Sessions extends Component {
138
138
  if (tab) {
139
139
  Object.assign(tab, update)
140
140
  }
141
- this.updateStoreTabs(tabs)
142
141
  return {
143
142
  tabs
144
143
  }
144
+ }, () => {
145
+ this.updateStoreTabs(this.state.tabs)
145
146
  })
146
147
  }
147
148
 
148
- addTab = (
149
- _tab,
150
- _index
151
- ) => {
149
+ addTab = (_tab, _index) => {
152
150
  this.setState((oldState) => {
153
151
  const tabs = copy(oldState.tabs)
154
152
  const index = typeof _index === 'undefined'
@@ -162,15 +160,17 @@ class Sessions extends Component {
162
160
  }
163
161
  tab.batch = this.props.batch
164
162
  tabs.splice(index, 0, tab)
165
- this.updateStoreTabs(tabs)
166
- this.updateStoreCurrentTabId(tab.id)
167
163
  return {
168
164
  currentTabId: tab.id,
169
165
  tabs
170
166
  }
167
+ }, () => {
168
+ this.updateStoreTabs(this.state.tabs)
169
+ this.updateStoreCurrentTabId(this.state.currentTabId)
171
170
  })
172
171
  }
173
172
 
173
+ // After
174
174
  delTab = (id) => {
175
175
  this.setState((oldState) => {
176
176
  const tabs = copy(oldState.tabs)
@@ -183,13 +183,16 @@ class Sessions extends Component {
183
183
  i = i ? i - 1 : i + 1
184
184
  const next = tabs[i] || {}
185
185
  up.currentTabId = next.id || ''
186
- this.updateStoreCurrentTabId(next.id)
187
186
  }
188
187
  up.tabs = tabs.filter(t => {
189
188
  return t.id !== id
190
189
  })
191
- this.updateStoreTabs(up.tabs)
192
190
  return up
191
+ }, () => {
192
+ this.updateStoreTabs(this.state.tabs)
193
+ if (this.state.currentTabId !== id) {
194
+ this.updateStoreCurrentTabId(this.state.currentTabId)
195
+ }
193
196
  })
194
197
  }
195
198
 
@@ -247,11 +250,15 @@ class Sessions extends Component {
247
250
  if (!matchedTab) {
248
251
  return
249
252
  }
250
- this.timer = setTimeout(window.store.triggerResize, 500)
251
- this.updateStoreCurrentTabId(id)
253
+
254
+ // Batch the updates
252
255
  this.setState({
253
256
  currentTabId: id
254
- }, this.postChange)
257
+ }, () => {
258
+ this.updateStoreCurrentTabId(id)
259
+ this.timer = setTimeout(window.store.triggerResize, 500)
260
+ this.postChange()
261
+ })
255
262
  }
256
263
 
257
264
  setTabs = tabs => {
@@ -56,6 +56,9 @@ export function shortcutExtend (Cls) {
56
56
  type,
57
57
  key
58
58
  } = event
59
+ if (this.cmdAddon) {
60
+ this.cmdAddon.handleKey(event)
61
+ }
59
62
  if (
60
63
  this.term &&
61
64
  key === 'Backspace' &&
@@ -483,7 +483,7 @@ export default class Tabs extends React.Component {
483
483
  menu={{ items }}
484
484
  placement='bottomRight'
485
485
  >
486
- <span className='tabs-dd-icon mg1l'>
486
+ <span className='tabs-dd-icon layout-dd-icon mg1l'>
487
487
  <Icon /> <DownOutlined />
488
488
  </span>
489
489
  </Dropdown>
@@ -7,6 +7,8 @@
7
7
  ::-webkit-scrollbar
8
8
  width 0
9
9
  display none
10
+ .not-system-ui.is-mac .layout-item.v1 .tabs-inner
11
+ margin-left 42px
10
12
  .not-system-ui.is-mac.not-webapp .layout-item.v1
11
13
  .tabs-inner
12
14
  margin-left 72px
@@ -25,8 +27,6 @@
25
27
  height 36px
26
28
  overflow-x scroll
27
29
  overflow-y hidden
28
- .layout-item.v1 .tabs-inner
29
- margin-left 42px
30
30
 
31
31
  .tabs-wrapper
32
32
  z-index 3
@@ -0,0 +1,75 @@
1
+ export class CommandTrackerAddon {
2
+ constructor () {
3
+ this.terminal = undefined
4
+ this.activeCommand = ''
5
+ this.currentCommand = ''
6
+ this.cursorPosition = 0
7
+ this.timeout = null
8
+ this.handleKey = this.debounce(this._handleKey, 200) // 10ms debounce
9
+ }
10
+
11
+ debounce = (func, wait) => {
12
+ return (...args) => {
13
+ const later = () => {
14
+ clearTimeout(this.timeout)
15
+ func.apply(this, args)
16
+ }
17
+
18
+ clearTimeout(this.timeout)
19
+ this.timeout = setTimeout(later, wait)
20
+ }
21
+ }
22
+
23
+ activate (terminal) {
24
+ this.terminal = terminal
25
+ }
26
+
27
+ dispose () {
28
+ this.term = null
29
+ if (this._disposables) {
30
+ this._disposables.forEach(d => d.dispose())
31
+ this._disposables.length = 0
32
+ }
33
+ if (this.timeout) {
34
+ clearTimeout(this.timeout)
35
+ this.timeout = null
36
+ }
37
+ }
38
+
39
+ handleData = (data) => {
40
+ // Handle regular input
41
+ this.activeCommand = this.activeCommand.slice(0, this.cursorPosition) + data + this.activeCommand.slice(this.cursorPosition)
42
+ this.cursorPosition += data.length
43
+ }
44
+
45
+ // This is now our internal handler
46
+ _handleKey = (e) => {
47
+ const { key } = e
48
+ if (key === 'Enter') {
49
+ // Command executed, reset
50
+ this.currentCommand = this.activeCommand
51
+ this.activeCommand = ''
52
+ this.cursorPosition = 0
53
+ } else if (key === 'Backspace') {
54
+ // Handle backspace
55
+ if (this.cursorPosition > 0) {
56
+ this.activeCommand = this.activeCommand.slice(0, this.cursorPosition - 1) + this.activeCommand.slice(this.cursorPosition)
57
+ this.cursorPosition--
58
+ }
59
+ } else if (key === 'ArrowLeft') {
60
+ // Move cursor left
61
+ if (this.cursorPosition > 0) {
62
+ this.cursorPosition--
63
+ }
64
+ } else if (key === 'ArrowRight') {
65
+ // Move cursor right
66
+ if (this.cursorPosition < this.activeCommand.length) {
67
+ this.cursorPosition++
68
+ }
69
+ }
70
+ }
71
+
72
+ getCurrentCommand () {
73
+ return this.activeCommand || this.currentCommand
74
+ }
75
+ }
@@ -48,8 +48,7 @@ import { createTerm, resizeTerm } from './terminal-apis'
48
48
  import { shortcutExtend, shortcutDescExtend } from '../shortcuts/shortcut-handler.js'
49
49
  import { KeywordHighlighterAddon } from './highlight-addon.js'
50
50
  import { getLocalFileInfo } from '../sftp/file-read.js'
51
- import { SerializeAddon } from '@xterm/addon-serialize'
52
- import strip from '@electerm/strip-ansi'
51
+ import { CommandTrackerAddon } from './command-tracker-addon.js'
53
52
  import { formatBytes } from '../../common/byte-format.js'
54
53
  import * as fs from './fs.js'
55
54
 
@@ -184,8 +183,13 @@ clear\r`
184
183
  this.fitAddon = null
185
184
  this.zmodemAddon = null
186
185
  this.searchAddon = null
187
- this.serializeAddon = null
188
186
  this.fitAddon = null
187
+ this.cmdAddon = null
188
+ // Clear the notification if it exists
189
+ if (this.socketCloseWarning) {
190
+ notification.destroy(this.socketCloseWarning.key)
191
+ this.socketCloseWarning = null
192
+ }
189
193
  }
190
194
 
191
195
  terminalConfigProps = [
@@ -928,17 +932,8 @@ clear\r`
928
932
  return result
929
933
  }
930
934
 
931
- // onKey = ({ key }) => {
932
- // if (key === '\r') {
933
- // this.getCmd()
934
- // }
935
- // }
936
-
937
935
  getCmd = () => {
938
- const str = this.serializeAddon.serialize()
939
- const arr = strip(str).split(/ +/)
940
- const len = arr.length
941
- return arr[len - 1]
936
+ return this.cmdAddon.getCurrentCommand()
942
937
  }
943
938
 
944
939
  getCwd = () => {
@@ -963,13 +958,15 @@ clear\r`
963
958
  }
964
959
 
965
960
  onData = (d) => {
966
- // runIdle(this.notifyOnData)
961
+ if (this.cmdAddon) {
962
+ this.cmdAddon.handleData(d)
963
+ }
967
964
  if (!d.includes('\r')) {
968
965
  delete this.userTypeExit
969
966
  } else {
970
- const data = this.getCmd()
967
+ const data = this.getCmd().trim()
971
968
  if (this.term.buffer.active.type !== 'alternate') {
972
- setTimeout(this.getCwd, 200)
969
+ this.timers.getCwd = setTimeout(this.getCwd, 200)
973
970
  }
974
971
  const exitCmds = [
975
972
  'exit',
@@ -1028,18 +1025,18 @@ clear\r`
1028
1025
 
1029
1026
  // term.on('keydown', this.handleEvent)
1030
1027
  this.fitAddon = new FitAddon()
1028
+ this.cmdAddon = new CommandTrackerAddon()
1031
1029
  this.searchAddon = new SearchAddon()
1032
1030
  const ligtureAddon = new LigaturesAddon()
1033
1031
  this.searchAddon.onDidChangeResults(this.onSearchResultsChange)
1034
1032
  const unicode11Addon = new Unicode11Addon()
1035
1033
  term.loadAddon(unicode11Addon)
1036
- this.serializeAddon = new SerializeAddon()
1037
- term.loadAddon(this.serializeAddon)
1038
1034
  term.loadAddon(ligtureAddon)
1039
1035
  // activate the new version
1040
1036
  term.unicode.activeVersion = '11'
1041
1037
  term.loadAddon(this.fitAddon)
1042
1038
  term.loadAddon(this.searchAddon)
1039
+ term.loadAddon(this.cmdAddon)
1043
1040
  term.onData(this.onData)
1044
1041
  this.term = term
1045
1042
  term.attachCustomKeyEventHandler(this.handleKeyboardEvent.bind(this))
@@ -1056,6 +1053,7 @@ clear\r`
1056
1053
  }
1057
1054
 
1058
1055
  runInitScript = () => {
1056
+ window.store.triggerResize()
1059
1057
  const {
1060
1058
  type,
1061
1059
  title,
@@ -34,7 +34,10 @@
34
34
  #container
35
35
  .xterm-viewport
36
36
  background-repeat no-repeat
37
- background-position 50% 50%
37
+ background-position center
38
+ background-color: transparent !important
39
+ z-index 1
40
+
38
41
 
39
42
  .terminal-not-active .xterm-text-layer
40
43
  opacity .74
@@ -4,10 +4,6 @@ import '@xterm/xterm/css/xterm.css'
4
4
  import '../common/trzsz'
5
5
  import 'firacode/distr/fira_code.css'
6
6
  import Main from '../components/main/index.jsx'
7
- import { notification } from 'antd'
8
- notification.config({
9
- placement: 'bottomRight'
10
- })
11
7
 
12
8
  const rootElement = createRoot(document.getElementById('container'))
13
9
  rootElement.render(
@@ -63,6 +63,7 @@ export default Store => {
63
63
 
64
64
  Store.prototype.triggerResize = function () {
65
65
  window.store.resizeTrigger = window.store.resizeTrigger ? 0 : 1
66
+ window.dispatchEvent(new Event('resize'))
66
67
  }
67
68
 
68
69
  Store.prototype.toggleTermFullscreen = function (terminalFullScreen) {
@@ -99,11 +99,6 @@ export default store => {
99
99
  return store._checkedKeys
100
100
  }).start()
101
101
 
102
- // autoRun(store, () => {
103
- // window.store.onLayoutChange()
104
- // return store.layout
105
- // }).start()
106
-
107
102
  autoRun(store, () => {
108
103
  const tabs = store.getTabs()
109
104
  const { currentTabId } = store
@@ -27,7 +27,7 @@ html
27
27
  }
28
28
  - if (!isDev)
29
29
  link(rel='stylesheet', href='css/' + version + '-basic.css')
30
- link(rel='stylesheet', href='css/' + version + '-index.css')
30
+ link(rel='stylesheet', href='css/' + version + '-electerm.css')
31
31
  style(id='theme-css').
32
32
  style(id='custom-css').
33
33
  body
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "1.50.31",
3
+ "version": "1.50.46",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",