@electerm/electerm-react 1.39.103 → 1.39.119

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.
@@ -0,0 +1,96 @@
1
+ // bookmark select tree
2
+ import createTitle from '../../common/create-title'
3
+ import { TreeSelect } from 'antd'
4
+
5
+ const e = window.translate
6
+
7
+ function buildTreeData (bookmarkGroups, tree) {
8
+ const cats = bookmarkGroups
9
+ const btree = cats
10
+ .reduce((p, k) => {
11
+ return {
12
+ ...p,
13
+ [k.id]: k
14
+ }
15
+ }, {})
16
+ function buildSubCats (id) {
17
+ const x = btree[id]
18
+ if (!x) {
19
+ return ''
20
+ }
21
+ const y = {
22
+ key: x.id,
23
+ value: x.id,
24
+ title: x.title
25
+ }
26
+ y.children = [
27
+ ...(x.bookmarkGroupIds || []).map(buildSubCats),
28
+ ...(x.bookmarkIds || []).map(buildLeaf)
29
+ ].filter(d => d)
30
+ if (y.children && !y.children.length) {
31
+ delete y.children
32
+ }
33
+ return y
34
+ }
35
+ function buildLeaf (id) {
36
+ const x = tree[id]
37
+ if (!x) {
38
+ return ''
39
+ }
40
+ return {
41
+ value: x.id,
42
+ key: x.id,
43
+ title: createTitle(x)
44
+ }
45
+ }
46
+ const level1 = cats.filter(d => d.level !== 2)
47
+ .map(d => {
48
+ const r = {
49
+ title: d.title,
50
+ value: d.id,
51
+ key: d.id,
52
+ children: [
53
+ ...(d.bookmarkGroupIds || []).map(buildSubCats),
54
+ ...(d.bookmarkIds || []).map(buildLeaf)
55
+ ].filter(d => d)
56
+ }
57
+ if (!r.children.length) {
58
+ return ''
59
+ }
60
+ return r
61
+ }).filter(d => d)
62
+ return level1
63
+ }
64
+
65
+ export default function BookmarkSelect (props) {
66
+ const {
67
+ bookmarks,
68
+ bookmarkGroups
69
+ } = props
70
+ const tree = bookmarks
71
+ .reduce((p, k) => {
72
+ return {
73
+ ...p,
74
+ [k.id]: k
75
+ }
76
+ }, {})
77
+
78
+ function onSelect (id) {
79
+ const item = tree[id]
80
+ if (item) {
81
+ item.bookmarkId = item.id
82
+ props.onSelect(item)
83
+ }
84
+ }
85
+ const treeData = buildTreeData(bookmarkGroups, tree)
86
+ const treeProps = {
87
+ treeData,
88
+ onChange: onSelect,
89
+ placeholder: e('chooseFromBookmarks'),
90
+ showSearch: true,
91
+ value: undefined
92
+ }
93
+ return (
94
+ <TreeSelect {...treeProps} />
95
+ )
96
+ }
@@ -17,6 +17,7 @@ import {
17
17
  authTypeMap
18
18
  } from '../../common/constants'
19
19
  import { useState } from 'react'
20
+ import BookmarkSelect from './bookmark-select'
20
21
 
21
22
  const FormItem = Form.Item
22
23
  const RadioButton = Radio.Button
@@ -129,7 +130,13 @@ export default function renderConnectionHopping (props) {
129
130
  </FormItem>
130
131
  )
131
132
  }
132
-
133
+ const treeProps = {
134
+ bookmarks: store.bookmarks.filter(d => {
135
+ return d.host && d.port && d.username
136
+ }),
137
+ bookmarkGroups: store.bookmarkGroups,
138
+ onSelect: handleFinish
139
+ }
133
140
  return (
134
141
  <div>
135
142
  <FormItem
@@ -144,6 +151,13 @@ export default function renderConnectionHopping (props) {
144
151
  initialValues={initialValues}
145
152
  >
146
153
  {renderList()}
154
+ <FormItem
155
+ {...formItemLayout}
156
+ label={e('chooseFromBookmarks')}
157
+ className='mg60b'
158
+ >
159
+ <BookmarkSelect {...treeProps} />
160
+ </FormItem>
147
161
  <FormItem
148
162
  {...formItemLayout}
149
163
  label={e('host')}
@@ -0,0 +1,19 @@
1
+ export default function onDrop (e, cls) {
2
+ e.preventDefault()
3
+ const { store } = window
4
+ const { quickCommands } = store
5
+ const idDragged = e.dataTransfer.getData('idDragged')
6
+ const tar = cls ? e.target.closest(cls) : e.target
7
+ const idDrop = tar.getAttribute('data-id')
8
+ const idDraggedIndex = quickCommands.findIndex(
9
+ ({ id }) => id === idDragged
10
+ )
11
+ const targetIndex = quickCommands.findIndex(
12
+ ({ id }) => id === idDrop
13
+ )
14
+ if (idDraggedIndex !== targetIndex) {
15
+ const [removed] = quickCommands.splice(idDraggedIndex, 1)
16
+ quickCommands.splice(targetIndex, 0, removed)
17
+ store.setItems('quickCommands', quickCommands)
18
+ }
19
+ }
@@ -14,6 +14,7 @@ import {
14
14
  PushpinOutlined
15
15
  } from '@ant-design/icons'
16
16
  import classNames from 'classnames'
17
+ import onDrop from './on-drop'
17
18
  import './qm.styl'
18
19
 
19
20
  const e = window.translate
@@ -90,23 +91,7 @@ export default class QuickCommandsFooterBox extends Component {
90
91
 
91
92
  // sort quick commands array when drop, so that the dragged item will be placed at the right position, e.target.getAttribute('data-id') would target item id, e.dataTransfer.getData('idDragged') would target dragged item id, then set window.store.quickCommands use window.store.setItems
92
93
  onDrop = e => {
93
- e.preventDefault()
94
- const { store } = window
95
- const { quickCommands } = store
96
- const idDragged = e.dataTransfer.getData('idDragged')
97
- const idDrop = e.target.getAttribute('data-id')
98
- const idDraggedIndex = quickCommands.findIndex(
99
- ({ id }) => id === idDragged
100
- )
101
- const targetIndex = quickCommands.findIndex(
102
- ({ id }) => id === idDrop
103
- )
104
- if (idDraggedIndex < targetIndex) {
105
- quickCommands.splice(targetIndex, 0, quickCommands.splice(idDraggedIndex, 1)[0])
106
- } else {
107
- quickCommands.splice(targetIndex + 1, 0, quickCommands.splice(idDraggedIndex, 1)[0])
108
- }
109
- store.setItems('quickCommands', quickCommands)
94
+ onDrop(e, '.qm-item')
110
95
  }
111
96
 
112
97
  renderNoCmd = () => {
@@ -8,6 +8,7 @@ import { Select } from 'antd'
8
8
  import classnames from 'classnames'
9
9
  import highlight from '../common/highlight'
10
10
  import QmTransport from './quick-command-transport'
11
+ import onDrop from './on-drop'
11
12
 
12
13
  const { Option } = Select
13
14
  const e = window.translate
@@ -22,7 +23,7 @@ export default class QuickCommandsList extends List {
22
23
  this.props.onClickItem(item)
23
24
  }
24
25
 
25
- handleChange = v => {
26
+ handleChangeLabel = v => {
26
27
  this.setState({
27
28
  labels: v
28
29
  })
@@ -42,23 +43,7 @@ export default class QuickCommandsList extends List {
42
43
 
43
44
  // adjust window.store.quickCommands array order when drop, so that the dragged item will be placed at the right position, e.target.getAttribute('data-id') would target item id, e.dataTransfer.getData('idDragged') would target dragged item id
44
45
  handleDrop = e => {
45
- e.preventDefault()
46
- const { store } = window
47
- const { quickCommands } = store
48
- const idDragged = e.dataTransfer.getData('idDragged')
49
- const idDrop = e.target.getAttribute('data-id')
50
- const idDraggedIndex = quickCommands.findIndex(
51
- ({ id }) => id === idDragged
52
- )
53
- const targetIndex = quickCommands.findIndex(
54
- ({ id }) => id === idDrop
55
- )
56
- if (idDraggedIndex < targetIndex) {
57
- quickCommands.splice(targetIndex, 0, quickCommands.splice(idDraggedIndex, 1)[0])
58
- } else {
59
- quickCommands.splice(targetIndex + 1, 0, quickCommands.splice(idDraggedIndex, 1)[0])
60
- }
61
- store.setItems('quickCommands', quickCommands)
46
+ onDrop(e)
62
47
  }
63
48
 
64
49
  renderItem = (item, i) => {
@@ -116,7 +101,7 @@ export default class QuickCommandsList extends List {
116
101
  placeholder: e('labels'),
117
102
  mode: 'multiple',
118
103
  value: this.state.labels,
119
- onChange: this.handleChange,
104
+ onChange: this.handleChangeLabel,
120
105
  style: {
121
106
  width: '100%'
122
107
  }
@@ -10,6 +10,7 @@ import {
10
10
  MinusCircleOutlined,
11
11
  PlusOutlined
12
12
  } from '@ant-design/icons'
13
+ import { useEffect } from 'react'
13
14
 
14
15
  const FormItem = Form.Item
15
16
  const FormList = Form.List
@@ -101,6 +102,10 @@ export default function KeywordForm (props) {
101
102
  )
102
103
  }
103
104
 
105
+ useEffect(() => {
106
+ formChild.resetFields()
107
+ }, [props.keywordFormReset])
108
+
104
109
  return (
105
110
  <div>
106
111
  <Form
@@ -0,0 +1,32 @@
1
+ import BookmarkTransport from '../tree-list/bookmark-transport'
2
+ import download from '../../common/download'
3
+ import time from '../../common/time'
4
+
5
+ export default class KeywordsTransport extends BookmarkTransport {
6
+ name = 'keywords-highlight'
7
+ beforeUpload = async (file) => {
8
+ const { store } = this.props
9
+ const txt = await window.fs.readFile(file.path)
10
+ try {
11
+ store.setConfig({
12
+ keywords: JSON.parse(txt)
13
+ })
14
+ } catch (e) {
15
+ store.onError(e)
16
+ }
17
+ setTimeout(this.props.resetKeywordForm, 100)
18
+ return false
19
+ }
20
+
21
+ renderEdit () {
22
+ return null
23
+ }
24
+
25
+ handleDownload = () => {
26
+ const { store } = this.props
27
+ const arr = store.config.keywords || []
28
+ const txt = JSON.stringify(arr, null, 2)
29
+ const stamp = time(undefined, 'YYYY-MM-DD-HH-mm-ss')
30
+ download('electerm-' + this.name + '-' + stamp + '.json', txt)
31
+ }
32
+ }
@@ -28,6 +28,7 @@ import mapper from '../../common/auto-complete-data-mapper'
28
28
  import KeywordForm from './keywords-form'
29
29
  import Link from '../common/external-link'
30
30
  import HelpIcon from '../common/help-icon'
31
+ import KeywordsTransport from './keywords-transport'
31
32
  import './setting.styl'
32
33
 
33
34
  const { Option } = Select
@@ -35,7 +36,8 @@ const e = window.translate
35
36
 
36
37
  export default class SettingTerminal extends Component {
37
38
  state = {
38
- ready: false
39
+ ready: false,
40
+ keywordFormReset: 1
39
41
  }
40
42
 
41
43
  componentDidMount () {
@@ -50,6 +52,12 @@ export default class SettingTerminal extends Component {
50
52
  clearTimeout(this.timer)
51
53
  }
52
54
 
55
+ resetKeywordForm = () => {
56
+ this.setState({
57
+ keywordFormReset: Date.now()
58
+ })
59
+ }
60
+
53
61
  handleResetAll = () => {
54
62
  this.saveConfig(
55
63
  deepCopy(defaultSettings)
@@ -411,6 +419,7 @@ export default class SettingTerminal extends Component {
411
419
  formData: {
412
420
  keywords
413
421
  },
422
+ keywordFormReset: this.state.keywordFormReset,
414
423
  submit: this.handleSubmitKeywords,
415
424
  themeConfig: getThemeConfig()
416
425
  }
@@ -469,6 +478,12 @@ export default class SettingTerminal extends Component {
469
478
  <HelpIcon
470
479
  title={tip}
471
480
  />
481
+ <span className='mg1l'>
482
+ <KeywordsTransport
483
+ store={this.props.store}
484
+ resetKeywordForm={this.resetKeywordForm}
485
+ />
486
+ </span>
472
487
  </div>
473
488
  <KeywordForm
474
489
  {...ps}
@@ -722,12 +722,12 @@ export default class FileSection extends React.Component {
722
722
  path,
723
723
  text,
724
724
  mode
725
- )
725
+ ).catch(window.store.onError)
726
726
  : await fs.writeFile(
727
727
  path,
728
728
  text,
729
729
  mode
730
- )
730
+ ).catch(window.store.onError)
731
731
  const data = {
732
732
  loading: false
733
733
  }
@@ -30,7 +30,6 @@ import deepCopy from 'json-deep-copy'
30
30
  import isValidPath from '../../common/is-valid-path'
31
31
  import memoizeOne from 'memoize-one'
32
32
  import postMessage from '../../common/post-msg'
33
- import { runCmd } from '../terminal/terminal-apis'
34
33
  import * as owner from './owner-list'
35
34
  import AddressBar from './address-bar'
36
35
  import getProxy from '../../common/get-proxy'
@@ -252,11 +251,7 @@ export default class Sftp extends Component {
252
251
  if (this.props.sftpPathFollowSsh && this.props.cwd) {
253
252
  return this.props.cwd
254
253
  }
255
- const home = await runCmd(
256
- this.props.pid,
257
- this.props.sessionId,
258
- 'pwd'
259
- ).catch(window.store.onError)
254
+ const home = await this.sftp.getHomeDir()
260
255
  if (home) {
261
256
  return home.trim()
262
257
  } else {
@@ -54,6 +54,7 @@ export default class AttachAddonCustom extends AttachAddon {
54
54
  onRead = (ev) => {
55
55
  const data = ev.target.result
56
56
  const { term } = this
57
+ term?.parent?.notifyOnData()
57
58
  const str = this.decoder.decode(data)
58
59
  if (term?.parent?.props.sftpPathFollowSsh && term?.buffer.active.type !== 'alternate') {
59
60
  const {
@@ -4,7 +4,7 @@ import generate from '../../common/uid'
4
4
  import { isEqual, pick, debounce, throttle } from 'lodash-es'
5
5
  import postMessage from '../../common/post-msg'
6
6
  import clone from '../../common/to-simple-obj'
7
- import runIdle from '../../common/run-idle'
7
+ // import runIdle from '../../common/run-idle'
8
8
  import {
9
9
  ReloadOutlined
10
10
  } from '@ant-design/icons'
@@ -783,7 +783,7 @@ class Term extends Component {
783
783
  onClear = () => {
784
784
  this.term.clear()
785
785
  this.term.focus()
786
- this.notifyOnData('')
786
+ // this.notifyOnData('')
787
787
  }
788
788
 
789
789
  isRemote = () => {
@@ -921,7 +921,7 @@ class Term extends Component {
921
921
  }
922
922
 
923
923
  onData = (d) => {
924
- runIdle(this.notifyOnData)
924
+ // runIdle(this.notifyOnData)
925
925
  if (!d.includes('\r')) {
926
926
  delete this.userTypeExit
927
927
  } else {
@@ -117,8 +117,21 @@ export default (Store) => {
117
117
  }
118
118
 
119
119
  Store.prototype.handleClearSyncSetting = async function () {
120
- window.store.setConfig({
121
- syncSetting: {}
120
+ const { store } = window
121
+ const currentSyncType = store.syncType
122
+ const currentSettings = store.config.syncSetting || {}
123
+ console.log('currentSettings: ', currentSyncType, currentSettings)
124
+ // Create a new object without the current sync type's settings
125
+ const updatedSettings = Object.keys(currentSettings).reduce((acc, key) => {
126
+ if (!key.startsWith(currentSyncType)) {
127
+ acc[key] = currentSettings[key]
128
+ }
129
+ return acc
130
+ }, {})
131
+ console.log('updatedSettings: ', updatedSettings)
132
+
133
+ store.setConfig({
134
+ syncSetting: updatedSettings
122
135
  })
123
136
  }
124
137
 
@@ -177,7 +190,10 @@ export default (Store) => {
177
190
  })
178
191
  }
179
192
  str = JSON.stringify(str)
180
- if (n === settingMap.bookmarks && pass) {
193
+ if (
194
+ (n === settingMap.bookmarks || n === settingMap.profiles) &&
195
+ pass
196
+ ) {
181
197
  str = await window.pre.runGlobalAsync('encryptAsync', str, pass)
182
198
  }
183
199
  objs[`${n}.json`] = {
@@ -346,7 +362,7 @@ export default (Store) => {
346
362
  Store.prototype.handleExportAllData = async function () {
347
363
  const { store } = window
348
364
  const objs = {}
349
- const names = store.getDataSyncNames(true)
365
+ const { names } = store.getDataSyncNames(true)
350
366
  for (const n of names) {
351
367
  objs[n] = store.getItems(n)
352
368
  const order = await getData(`${n}:order`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "1.39.103",
3
+ "version": "1.39.119",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",