@electerm/electerm-react 1.51.3 → 1.51.18

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 (86) hide show
  1. package/client/common/constants.js +15 -1
  2. package/client/common/db.js +10 -9
  3. package/client/common/default-setting.js +0 -1
  4. package/client/common/is-color-dark.js +15 -11
  5. package/client/common/new-terminal.js +2 -5
  6. package/client/common/reverse-color.js +12 -0
  7. package/client/common/ws.js +4 -1
  8. package/client/components/batch-op/batch-op.jsx +16 -5
  9. package/client/components/bookmark-form/index.jsx +1 -1
  10. package/client/components/bookmark-form/render-connection-hopping.jsx +25 -2
  11. package/client/components/bookmark-form/ssh-form.jsx +4 -25
  12. package/client/components/bookmark-form/tree-delete.jsx +5 -10
  13. package/client/components/bookmark-form/use-submit.jsx +6 -15
  14. package/client/components/bookmark-form/use-ui.jsx +1 -2
  15. package/client/components/common/connection-hopping-warning-text.jsx +36 -0
  16. package/client/components/common/drag-handle.jsx +60 -0
  17. package/client/components/common/drag-handle.styl +12 -0
  18. package/client/components/context-menu/context-menu.styl +5 -5
  19. package/client/components/context-menu/history.jsx +2 -11
  20. package/client/components/context-menu/sub-tab-menu.jsx +1 -1
  21. package/client/components/footer/footer-entry.jsx +1 -6
  22. package/client/components/layout/layout-item.jsx +2 -2
  23. package/client/components/layout/layout.jsx +3 -2
  24. package/client/components/main/connection-hopping-warnning.jsx +45 -0
  25. package/client/components/main/error-wrapper.jsx +120 -5
  26. package/client/components/main/main.jsx +32 -8
  27. package/client/components/main/upgrade.jsx +4 -9
  28. package/client/components/main/wrapper.styl +2 -1
  29. package/client/components/profile/profile-form-ssh.jsx +1 -1
  30. package/client/components/rdp/resolution-edit.jsx +3 -5
  31. package/client/components/session/session.jsx +22 -3
  32. package/client/components/session/session.styl +3 -2
  33. package/client/components/setting-panel/list.styl +0 -1
  34. package/client/components/setting-panel/on-tree-drop.js +5 -5
  35. package/client/components/setting-panel/setting-common.jsx +28 -7
  36. package/client/components/setting-panel/setting-modal.jsx +0 -12
  37. package/client/components/setting-panel/setting-terminal.jsx +7 -4
  38. package/client/components/sftp/confirm-modal-store.jsx +3 -11
  39. package/client/components/sftp/file-mode-modal.jsx +2 -2
  40. package/client/components/sftp/sftp-entry.jsx +4 -7
  41. package/client/components/sftp/transfer-conflict-store.jsx +70 -69
  42. package/client/components/sftp/transport-action-store.jsx +42 -49
  43. package/client/components/sftp/transports-action-store.jsx +15 -15
  44. package/client/components/sftp/transports-ui-store.jsx +9 -5
  45. package/client/components/side-panel-r/side-panel-r.jsx +13 -40
  46. package/client/components/sidebar/bookmark-select.jsx +1 -4
  47. package/client/components/sidebar/bookmark.jsx +4 -63
  48. package/client/components/sidebar/history-item.jsx +34 -0
  49. package/client/components/sidebar/history.jsx +17 -52
  50. package/client/components/sidebar/index.jsx +5 -40
  51. package/client/components/sidebar/side-panel.jsx +27 -51
  52. package/client/components/sidebar/sidebar-panel.jsx +107 -0
  53. package/client/components/sidebar/sidebar.styl +14 -9
  54. package/client/components/sidebar/transfer-list-control.jsx +1 -0
  55. package/client/components/sidebar/transfer.styl +1 -1
  56. package/client/components/sidebar/transport-ui.jsx +179 -37
  57. package/client/components/ssh-config/load-ssh-configs.jsx +106 -0
  58. package/client/components/ssh-config/ssh-config-item.jsx +26 -0
  59. package/client/components/ssh-config/ssh-config-load-notify.jsx +60 -0
  60. package/client/components/tabs/index.jsx +4 -4
  61. package/client/components/tabs/tab.jsx +28 -20
  62. package/client/components/tabs/tabs.styl +6 -1
  63. package/client/components/terminal/index.jsx +4 -18
  64. package/client/components/tree-list/bookmark-toolbar.jsx +203 -0
  65. package/client/components/tree-list/bookmark-transport.jsx +2 -0
  66. package/client/components/tree-list/tree-list.jsx +33 -42
  67. package/client/entry/worker.js +5 -3
  68. package/client/store/bookmark-group.js +5 -18
  69. package/client/store/bookmark.js +43 -1
  70. package/client/store/common.js +13 -9
  71. package/client/store/db-upgrade.js +0 -2
  72. package/client/store/index.js +45 -53
  73. package/client/store/init-state.js +20 -23
  74. package/client/store/item.js +0 -19
  75. package/client/store/load-data.js +7 -10
  76. package/client/store/setting.js +10 -66
  77. package/client/store/sidebar.js +7 -8
  78. package/client/store/sync.js +7 -8
  79. package/client/store/tab.js +93 -14
  80. package/client/store/terminal-theme.js +1 -1
  81. package/client/store/transfer-history.js +3 -9
  82. package/client/store/transfer-list.js +67 -75
  83. package/client/store/ui-theme.js +0 -9
  84. package/client/store/watch.js +17 -9
  85. package/package.json +1 -1
  86. package/client/components/setting-panel/tab-history.jsx +0 -43
@@ -98,7 +98,6 @@ export const paneMap = buildConst([
98
98
  export const settingMap = buildConst([
99
99
  'setting',
100
100
  'bookmarks',
101
- 'history',
102
101
  'terminalThemes',
103
102
  'bookmarkGroups',
104
103
  'quickCommands',
@@ -307,6 +306,7 @@ export const sshTunnelHelpLink = 'https://github.com/electerm/electerm/wiki/How-
307
306
  export const batchOpHelpLink = 'https://github.com/electerm/electerm/wiki/batch-operation'
308
307
  export const proxyHelpLink = 'https://github.com/electerm/electerm/wiki/proxy-format'
309
308
  export const regexHelpLink = 'https://github.com/electerm/electerm/wiki/Terminal-keywords-highlight-regular-expression-exmaples'
309
+ export const connectionHoppingWikiLink = 'https://github.com/electerm/electerm/wiki/Connection-Hopping-Behavior-Change-in-electerm-since-v1.50.65'
310
310
  export const modals = {
311
311
  hide: 0,
312
312
  setting: 1,
@@ -398,3 +398,17 @@ export const syncDataMaps = {
398
398
  profiles: ['profiles'],
399
399
  addressBookmarks: ['addressBookmarks']
400
400
  }
401
+ export const terminalTypes = [
402
+ 'xterm-256color',
403
+ 'xterm-new',
404
+ 'xterm-color',
405
+ 'xterm-vt220',
406
+ 'xterm',
407
+ 'linux',
408
+ 'vt100',
409
+ 'ansi',
410
+ 'rxvt'
411
+ ]
412
+ export const sshConfigLoadKey = 'ssh-config-loaded'
413
+ export const sshConfigKey = 'ignore-ssh-config'
414
+ export const connectionHoppingWarnKey = 'connectionHoppingWarnned'
@@ -5,7 +5,7 @@
5
5
  import {
6
6
  settingMap
7
7
  } from '../common/constants'
8
- import { without, isArray, findIndex } from 'lodash-es'
8
+ import { without, isArray } from 'lodash-es'
9
9
  import handleError from './error-handler'
10
10
  import generate from './uid'
11
11
  import safeParse from './to-simple-obj'
@@ -30,8 +30,7 @@ export const dbNames = without(
30
30
 
31
31
  export const dbNamesForWatch = without(
32
32
  Object.keys(settingMap),
33
- settingMap.setting,
34
- settingMap.history
33
+ settingMap.setting
35
34
  )
36
35
 
37
36
  /**
@@ -146,10 +145,12 @@ export async function getData (name) {
146
145
  export async function fetchInitData (dbName) {
147
146
  const res = await find(dbName)
148
147
  const order = await getData(`${dbName}:order`)
149
- const r = res.sort((a, b) => {
150
- const ai = findIndex(order, r => r === a.id)
151
- const bi = findIndex(order, r => r === b.id)
152
- return ai - bi
153
- })
154
- return JSON.stringify(r)
148
+ if (order && order.length) {
149
+ res.sort((a, b) => {
150
+ const ai = order.findIndex(r => r === a.id)
151
+ const bi = order.findIndex(r => r === b.id)
152
+ return ai - bi
153
+ })
154
+ }
155
+ return JSON.stringify(res)
155
156
  }
@@ -39,7 +39,6 @@ export default {
39
39
  initDefaultTabOnStart: true,
40
40
  screenReaderMode: false,
41
41
  autoRefreshWhenSwitchToSftp: false,
42
- hideSshConfig: false,
43
42
  addTimeStampToTermLog: false,
44
43
  sftpPathFollowSsh: false,
45
44
  keepaliveInterval: 0,
@@ -17,17 +17,21 @@ function expandShorthandColor (color) {
17
17
  }
18
18
 
19
19
  export default function isColorDark (_color) {
20
- let color = expandShorthandColor(_color)
21
- if (color.charAt(0) === '#') {
22
- color = color.slice(1) // Remove the '#' if present
23
- }
24
- const r = parseInt(color.substr(0, 2), 16)
25
- const g = parseInt(color.substr(2, 2), 16)
26
- const b = parseInt(color.substr(4, 2), 16)
20
+ try {
21
+ let color = expandShorthandColor(_color)
22
+ if (color.charAt(0) === '#') {
23
+ color = color.slice(1) // Remove the '#' if present
24
+ }
25
+ const r = parseInt(color.substr(0, 2), 16)
26
+ const g = parseInt(color.substr(2, 2), 16)
27
+ const b = parseInt(color.substr(4, 2), 16)
27
28
 
28
- // Formula to determine brightness
29
- const brightness = (r * 299 + g * 587 + b * 114) / 1000
29
+ // Formula to determine brightness
30
+ const brightness = (r * 299 + g * 587 + b * 114) / 1000
30
31
 
31
- // Decide based on brightness threshold
32
- return brightness < 128 // You can adjust this threshold as needed
32
+ // Decide based on brightness threshold
33
+ return brightness < 128 // You can adjust this threshold as needed
34
+ } catch (e) {
35
+ return true
36
+ }
33
37
  }
@@ -11,11 +11,11 @@ const e = window.translate
11
11
  window.et.tabCount = 0
12
12
 
13
13
  export function updateCount (tab) {
14
- tab.tabCount = window.et.tabCount
15
14
  window.et.tabCount++
15
+ return window.et.tabCount
16
16
  }
17
17
 
18
- export default (removeTitle, noUpdateCount) => {
18
+ export default (removeTitle) => {
19
19
  const res = {
20
20
  id: uid(),
21
21
  status: 'processing',
@@ -25,8 +25,5 @@ export default (removeTitle, noUpdateCount) => {
25
25
  if (removeTitle) {
26
26
  delete res.title
27
27
  }
28
- if (!noUpdateCount) {
29
- updateCount(res)
30
- }
31
28
  return res
32
29
  }
@@ -0,0 +1,12 @@
1
+ export function getReverseColor (hex) {
2
+ // Check if the input is a valid hex color code
3
+ if (!/^#[0-9a-fA-F]{6}$/.test(hex)) {
4
+ return '#0088cc'
5
+ }
6
+ // Convert the hex color code to an integer
7
+ const num = parseInt(hex.slice(1), 16)
8
+ // Bitwise XOR the integer with 0xFFFFFF to get the reverse color
9
+ const reverse = num ^ 0xFFFFFF
10
+ // Convert the reverse color to a hex string and pad with zeros if needed
11
+ return '#' + reverse.toString(16).padStart(6, '0')
12
+ }
@@ -5,6 +5,7 @@
5
5
  import generate from './uid'
6
6
  import wait from './wait'
7
7
  import copy from 'json-deep-copy'
8
+ import { pick } from 'lodash-es'
8
9
 
9
10
  const onces = {}
10
11
  const wss = {}
@@ -151,7 +152,9 @@ export default (type, id, sessionId = '', sftpId = '', persist) => {
151
152
  id,
152
153
  sessionId,
153
154
  sftpId,
154
- window.store.config
155
+ pick(window.store.config, [
156
+ 'host', 'port', 'tokenElecterm'
157
+ ])
155
158
  ]
156
159
  })
157
160
  onces[id] = {
@@ -173,11 +173,15 @@ export default class BatchOp extends PureComponent {
173
173
  run = async (conf, index) => {
174
174
  this.updateState('working', index)
175
175
  let tab = await this.createTab(conf)
176
- .then(r => r)
177
176
  .catch(err => {
177
+ console.log('create tab error', err)
178
+ if (this.ref) {
179
+ this.ref.stop()
180
+ delete this.ref
181
+ }
178
182
  return 'Error: ' + err.message
179
183
  })
180
- if (!tab) {
184
+ if (typeof tab === 'string') {
181
185
  return this.updateState(tab, index)
182
186
  }
183
187
 
@@ -189,9 +193,16 @@ export default class BatchOp extends PureComponent {
189
193
  }
190
194
  if (conf.remotePath) {
191
195
  this.updateState('creating sftp', index)
192
- tab = await this.createSftp(tab)
193
- if (!tab) {
194
- return this.updateState('Error: ' + tab, index)
196
+ tab = await this.createSftp(tab).catch(err => {
197
+ console.log('create sftp error', err)
198
+ if (this.ref2) {
199
+ this.ref2.stop()
200
+ delete this.ref2
201
+ }
202
+ return 'Error: ' + err.message
203
+ })
204
+ if (typeof tab === 'string') {
205
+ return this.updateState(tab, index)
195
206
  }
196
207
  this.updateState('sftp created', index)
197
208
  this.updateState('transferring file', index)
@@ -125,7 +125,7 @@ export default class BookmarkIndex extends PureComponent {
125
125
  const {
126
126
  type
127
127
  } = this.props
128
- if (type !== settingMap.bookmarks && type !== settingMap.history) {
128
+ if (type !== settingMap.bookmarks) {
129
129
  return null
130
130
  }
131
131
  const { ready } = this.state
@@ -6,7 +6,10 @@ import {
6
6
  Button,
7
7
  Table
8
8
  } from 'antd'
9
- import { formItemLayout, tailFormItemLayout } from '../../common/form-layout'
9
+ import {
10
+ formItemLayout,
11
+ tailFormItemLayout
12
+ } from '../../common/form-layout'
10
13
  import {
11
14
  MinusCircleFilled,
12
15
  PlusOutlined
@@ -14,10 +17,13 @@ import {
14
17
  import RenderAuth from './render-auth-ssh'
15
18
  import uid from '../../common/uid'
16
19
  import {
17
- authTypeMap
20
+ authTypeMap,
21
+ connectionHoppingWarnKey
18
22
  } from '../../common/constants'
19
23
  import { useState } from 'react'
24
+ import ConnectionHoppingWarningText from '../common/connection-hopping-warning-text'
20
25
  import BookmarkSelect from './bookmark-select'
26
+ import * as ls from '../../common/safe-local-storage'
21
27
 
22
28
  const FormItem = Form.Item
23
29
  const RadioButton = Radio.Button
@@ -35,6 +41,12 @@ export default function renderConnectionHopping (props) {
35
41
  port: 22,
36
42
  authType: authTypeMap.password
37
43
  })
44
+ const [showWarn, setShowWarn] = useState(
45
+ window.store.hasOldConnectionHoppingBookmark && ls.getItem(connectionHoppingWarnKey) !== 'yes'
46
+ )
47
+ function closeWarn () {
48
+ setShowWarn(false)
49
+ }
38
50
  const [list, setList] = useState(formData.connectionHoppings || [])
39
51
  function onChangeAuthType (e) {
40
52
  editState(old => {
@@ -139,6 +151,16 @@ export default function renderConnectionHopping (props) {
139
151
  </FormItem>
140
152
  )
141
153
  }
154
+ function renderWarn () {
155
+ if (!showWarn) {
156
+ return null
157
+ }
158
+ return (
159
+ <FormItem {...tailFormItemLayout}>
160
+ <ConnectionHoppingWarningText closeWarn={closeWarn} />
161
+ </FormItem>
162
+ )
163
+ }
142
164
  const treeProps = {
143
165
  bookmarks: store.bookmarks.filter(d => {
144
166
  return d.host && d.port && d.username
@@ -160,6 +182,7 @@ export default function renderConnectionHopping (props) {
160
182
  initialValues={initialValues}
161
183
  >
162
184
  {renderList()}
185
+ {renderWarn()}
163
186
  <FormItem
164
187
  {...formItemLayout}
165
188
  label={e('chooseFromBookmarks')}
@@ -5,7 +5,7 @@ import { PureComponent } from 'react'
5
5
  import {
6
6
  message
7
7
  } from 'antd'
8
- import { findIndex, uniq, isEqual, pick } from 'lodash-es'
8
+ import { uniq, isEqual, pick } from 'lodash-es'
9
9
  import copy from 'json-deep-copy'
10
10
  import generate from '../../common/uid'
11
11
  import {
@@ -96,13 +96,11 @@ export default class BookmarkForm extends PureComponent {
96
96
  }
97
97
 
98
98
  updateBookmarkGroups = (bookmarkGroups, bookmark, categoryId) => {
99
- let index = findIndex(
100
- bookmarkGroups,
99
+ let index = bookmarkGroups.findIndex(
101
100
  bg => bg.id === categoryId
102
101
  )
103
102
  if (index < 0) {
104
- index = findIndex(
105
- bookmarkGroups,
103
+ index = bookmarkGroups.findIndex(
106
104
  bg => bg.id === defaultBookmarkGroupId
107
105
  )
108
106
  }
@@ -167,19 +165,6 @@ export default class BookmarkForm extends PureComponent {
167
165
  const bookmarkGroups = copy(
168
166
  this.props.bookmarkGroups
169
167
  )
170
- if (type === settingMap.history) {
171
- obj.id = generate()
172
- runIdle(() => {
173
- addItem(obj, settingMap.bookmarks)
174
- })
175
- this.updateBookmarkGroups(
176
- bookmarkGroups,
177
- obj,
178
- categoryId
179
- )
180
- message.success('OK', 3)
181
- return
182
- }
183
168
  if (!obj.id.startsWith(newBookmarkIdPrefix)) {
184
169
  const tar = copy(obj)
185
170
  delete tar.id
@@ -196,11 +181,6 @@ export default class BookmarkForm extends PureComponent {
196
181
  }
197
182
  } else {
198
183
  obj.id = generate()
199
- if (evt !== 'save' && evt !== 'saveAndCreateNew') {
200
- runIdle(() => {
201
- addItem(obj, settingMap.history)
202
- })
203
- }
204
184
  runIdle(() => {
205
185
  addItem(obj, settingMap.bookmarks)
206
186
  })
@@ -217,8 +197,7 @@ export default class BookmarkForm extends PureComponent {
217
197
  }
218
198
 
219
199
  setNewItem = (
220
- settingItem = getInitItem([],
221
- settingMap.bookmarks)
200
+ settingItem = getInitItem([], settingMap.bookmarks)
222
201
  ) => {
223
202
  const { store } = this.props
224
203
  this.props.store.storeAssign({
@@ -4,22 +4,17 @@ import {
4
4
  Button
5
5
  } from 'antd'
6
6
  import { defaultBookmarkGroupId, settingMap } from '../../common/constants'
7
+ import deepCopy from 'json-deep-copy'
7
8
 
8
9
  const e = window.translate
9
10
 
10
11
  export default class BookmarkTreeDelete extends StartSessionSelect {
11
12
  onExpand = (expandedKeys) => {
12
- window.store.setState(
13
- 'expandedKeys',
14
- expandedKeys
15
- )
13
+ window.store.expandedKeys = deepCopy(expandedKeys)
16
14
  }
17
15
 
18
16
  onCheck = (checkedKeys) => {
19
- window.store.setState(
20
- 'checkedKeys',
21
- checkedKeys
22
- )
17
+ window.store.checkedKeys = deepCopy(checkedKeys)
23
18
  }
24
19
 
25
20
  handleDel = () => {
@@ -42,13 +37,13 @@ export default class BookmarkTreeDelete extends StartSessionSelect {
42
37
  const arr = checkedKeys.filter(d => d !== defaultBookmarkGroupId)
43
38
  store.delItems(arr, settingMap.bookmarks)
44
39
  store.delItems(arr, settingMap.bookmarkGroups)
45
- store.setState('checkedKeys', [])
40
+ store.checkedKeys = []
46
41
  }
47
42
 
48
43
  handleCancel = () => {
49
44
  const { store } = window
50
45
  store.bookmarkSelectMode = false
51
- store.setState('checkedKeys', [])
46
+ store.checkedKeys = []
52
47
  }
53
48
 
54
49
  render () {
@@ -10,9 +10,6 @@ import {
10
10
  Button,
11
11
  Form
12
12
  } from 'antd'
13
- import {
14
- settingMap
15
- } from '../../common/constants'
16
13
  import { tailFormItemLayout } from '../../common/form-layout'
17
14
  import useFuncs from './use-form-funcs'
18
15
 
@@ -37,18 +34,12 @@ export default function useBookmarkSubmit (props) {
37
34
  className='mg1r mg1b'
38
35
  >{e('saveAndConnect')}
39
36
  </Button>
40
- {
41
- settingMap.history === props.type
42
- ? null
43
- : (
44
- <Button
45
- type='primary'
46
- className='mg1r mg1b'
47
- onClick={saveAndCreateNew}
48
- >{e('saveAndCreateNew')}
49
- </Button>
50
- )
51
- }
37
+ <Button
38
+ type='primary'
39
+ className='mg1r mg1b'
40
+ onClick={saveAndCreateNew}
41
+ >{e('saveAndCreateNew')}
42
+ </Button>
52
43
  <Button
53
44
  type='dashed'
54
45
  className='mg1r mg1b'
@@ -16,7 +16,7 @@ import {
16
16
  import { formItemLayout } from '../../common/form-layout'
17
17
  import defaultSettings from '../../common/default-setting'
18
18
  import mapper from '../../common/auto-complete-data-mapper'
19
- import { defaultEnvLang } from '../../common/constants'
19
+ import { defaultEnvLang, terminalTypes } from '../../common/constants'
20
20
 
21
21
  const FormItem = Form.Item
22
22
  const e = window.translate
@@ -26,7 +26,6 @@ export default function useBookmarkFormUI (props) {
26
26
  fontFamily: defaultFontFamily,
27
27
  fontSize: defaultFontSize
28
28
  } = defaultSettings
29
- const { terminalTypes } = props.store.config
30
29
  return [
31
30
  <FormItem
32
31
  {...formItemLayout}
@@ -0,0 +1,36 @@
1
+ import {
2
+ Button
3
+ } from 'antd'
4
+ import Link from './external-link'
5
+ import {
6
+ connectionHoppingWikiLink,
7
+ connectionHoppingWarnKey
8
+ } from '../../common/constants'
9
+ import * as ls from '../../common/safe-local-storage'
10
+
11
+ const e = window.translate
12
+
13
+ export default function ConnectionHoppingWarningText (props) {
14
+ function handleRead () {
15
+ ls.setItem(connectionHoppingWarnKey, 'yes')
16
+ props.closeWarn()
17
+ }
18
+ return (
19
+ <div className='pd1'>
20
+ <div className='pd1b'>
21
+ <span>{e('connectionHoppingWarning')}</span>
22
+ </div>
23
+ <div className='pd1b'>
24
+ <Link to={connectionHoppingWikiLink}>{connectionHoppingWikiLink}</Link>
25
+ </div>
26
+ <div className='pd1b'>
27
+ <Button
28
+ onClick={handleRead}
29
+ size='small'
30
+ >
31
+ {e('haveRead')}
32
+ </Button>
33
+ </div>
34
+ </div>
35
+ )
36
+ }
@@ -0,0 +1,60 @@
1
+ import { useCallback, useRef, useState, memo } from 'react'
2
+ import './drag-handle.styl'
3
+
4
+ export default memo(function DragHandle (props) {
5
+ const [isDragging, setIsDragging] = useState(false)
6
+ const dragStartRef = useRef(false)
7
+ const clientXRef = useRef(0)
8
+ const {
9
+ max,
10
+ min,
11
+ width,
12
+ left = true
13
+ } = props
14
+
15
+ const calc = useCallback((clientX) => {
16
+ let nw = left
17
+ ? clientX - clientXRef.current + width
18
+ : clientXRef.current - clientX + width
19
+ if (nw < min) {
20
+ nw = min
21
+ } else if (nw > max) {
22
+ nw = max
23
+ }
24
+ return nw
25
+ }, [props.max, props.min, props.left])
26
+
27
+ const handleMousedown = useCallback((e) => {
28
+ e.stopPropagation()
29
+ setIsDragging(true)
30
+ dragStartRef.current = true
31
+ clientXRef.current = e.clientX
32
+ window.addEventListener('mouseup', handleMouseup)
33
+ window.addEventListener('mousemove', handleMousemove)
34
+ }, [])
35
+
36
+ const handleMouseup = useCallback((e) => {
37
+ setIsDragging(false)
38
+ dragStartRef.current = false
39
+ const nw = calc(e.clientX)
40
+ props.onDragEnd(nw)
41
+ window.store.onResize()
42
+ window.removeEventListener('mouseup', handleMouseup)
43
+ window.removeEventListener('mousemove', handleMousemove)
44
+ }, [])
45
+
46
+ const handleMousemove = useCallback((e) => {
47
+ const nw = calc(e.clientX)
48
+ props.onDragMove(nw)
49
+ }, [width])
50
+ const divProps = {
51
+ className: 'drag-handle' + (isDragging ? ' dragging' : ''),
52
+ onMouseDown: handleMousedown,
53
+ draggable: false
54
+ }
55
+ return (
56
+ <div
57
+ {...divProps}
58
+ />
59
+ )
60
+ })
@@ -0,0 +1,12 @@
1
+
2
+ .drag-handle
3
+ position absolute
4
+ right 0
5
+ top 0
6
+ width 3px
7
+ bottom 0
8
+ cursor ew-resize
9
+ display none
10
+ z-index 201
11
+ &.dragging
12
+ background #08c
@@ -2,7 +2,7 @@
2
2
  .context-menu
3
3
  position: absolute
4
4
  width 280px
5
- background main-dark
5
+ background main
6
6
  box-shadow 0px 0px 3px 3px alpha(main-dark, .35)
7
7
  padding 10px 0
8
8
  z-index 999
@@ -20,7 +20,7 @@
20
20
  line-height 28px
21
21
  padding 0 16px
22
22
  &:hover
23
- background #000
23
+ background #08c
24
24
  color #eee
25
25
  cursor pointer
26
26
  &.disabled
@@ -47,7 +47,7 @@
47
47
  position absolute
48
48
  left 100%
49
49
  top 0
50
- background main-dark
50
+ background main
51
51
  box-shadow 0px 0px 3px 3px alpha(main, .35)
52
52
  max-height 300px
53
53
  overflow-y scroll
@@ -62,8 +62,8 @@
62
62
  white-space nowrap
63
63
  text-overflow ellipsis
64
64
  &:hover, &.active
65
- background-color primary
66
- color contrastColor(primary)
65
+ background-color #08c
66
+ color #eee
67
67
  .bookmarks-sub-context-menu
68
68
  width 380px
69
69
  padding 20px 10px 10px 20px
@@ -1,21 +1,12 @@
1
- import { createTitleWithTag } from '../../common/create-title'
1
+ import HistoryItem from '../sidebar/history-item'
2
2
 
3
3
  export default function HistorySubMenu (props) {
4
- const { store } = window
5
4
  return (
6
5
  <div className='sub-context-menu'>
7
6
  {
8
7
  props.history.map(item => {
9
- const title = createTitleWithTag(item)
10
8
  return (
11
- <div
12
- className='sub-context-menu-item'
13
- title={title}
14
- key={item.id}
15
- onClick={() => store.onSelectHistory(item.id)}
16
- >
17
- {title}
18
- </div>
9
+ <HistoryItem key={item.id} item={item} />
19
10
  )
20
11
  })
21
12
  }
@@ -3,7 +3,7 @@ import { createTitleWithTag } from '../../common/create-title'
3
3
 
4
4
  export default class TabsSubMenuChild extends PureComponent {
5
5
  handleClick = () => {
6
- window.store.onChangeTabId(this.props.item.id)
6
+ window.store.changeActiveTabId(this.props.item.id)
7
7
  }
8
8
 
9
9
  render () {
@@ -18,12 +18,7 @@ const e = window.translate
18
18
 
19
19
  export default auto(function FooterEntry (props) {
20
20
  function handleInfoPanel () {
21
- const { store } = window
22
- store.rightPanelVisible = !store.rightPanelVisible
23
- postMessage({
24
- action: terminalActions.showInfoPanel,
25
- activeTabId: store.activeTabId
26
- })
21
+ window.store.openInfoPanel()
27
22
  }
28
23
 
29
24
  function batchInput (cmd, selectedTabIds) {
@@ -18,8 +18,8 @@ export default function LayoutItem (props) {
18
18
  }
19
19
  let currentElement = target
20
20
  while (currentElement) {
21
- if (currentElement.classList && currentElement.classList.contains('tab')) {
22
- return
21
+ if (currentElement.classList && currentElement.classList.contains('layout-item')) {
22
+ break
23
23
  }
24
24
  currentElement = currentElement.parentElement
25
25
  }
@@ -40,9 +40,10 @@ export default auto(function Layout (props) {
40
40
  rightPanelVisible,
41
41
  rightPanelPinned,
42
42
  rightPanelWidth,
43
- resizeTrigger
43
+ resizeTrigger,
44
+ inActiveTerminal
44
45
  } = props.store
45
- const h = height - footerHeight - (pinnedQuickCommandBar ? quickCommandBoxHeight : 0) + resizeTrigger
46
+ const h = height - footerHeight - (inActiveTerminal && pinnedQuickCommandBar ? quickCommandBoxHeight : 0) + resizeTrigger
46
47
  const l = pinned ? 43 + leftSidebarWidth : 43
47
48
  const r = rightPanelVisible && rightPanelPinned ? rightPanelWidth : 0
48
49
  return {