@electerm/electerm-react 1.34.30

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 (273) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +31 -0
  3. package/client/common/auto-complete-data-mapper.js +6 -0
  4. package/client/common/byte-format.js +14 -0
  5. package/client/common/class.js +52 -0
  6. package/client/common/clipboard.js +49 -0
  7. package/client/common/constants.js +308 -0
  8. package/client/common/create-lang-edit-link.js +7 -0
  9. package/client/common/create-title.js +29 -0
  10. package/client/common/db-fix.js +24 -0
  11. package/client/common/db.js +155 -0
  12. package/client/common/download-mirrors.js +10 -0
  13. package/client/common/download.js +16 -0
  14. package/client/common/error-handler.jsx +27 -0
  15. package/client/common/fetch-from-server.js +47 -0
  16. package/client/common/fetch.jsx +71 -0
  17. package/client/common/find-bookmark-group-id.js +15 -0
  18. package/client/common/find-parent.js +30 -0
  19. package/client/common/form-layout.js +27 -0
  20. package/client/common/fs.js +21 -0
  21. package/client/common/get-proxy.js +8 -0
  22. package/client/common/id-with-stamp.js +10 -0
  23. package/client/common/index-sorter.js +4 -0
  24. package/client/common/init-setting-item.js +32 -0
  25. package/client/common/is-absolute-path.js +3 -0
  26. package/client/common/is-ip.js +16 -0
  27. package/client/common/is-valid-path.js +7 -0
  28. package/client/common/key-control-pressed.js +13 -0
  29. package/client/common/key-pressed.js +13 -0
  30. package/client/common/key-shift-pressed.js +7 -0
  31. package/client/common/mode2permission.js +81 -0
  32. package/client/common/new-terminal.js +31 -0
  33. package/client/common/parse-int10.js +3 -0
  34. package/client/common/parse-json-safe.js +11 -0
  35. package/client/common/pass-enc.js +25 -0
  36. package/client/common/post-msg.js +3 -0
  37. package/client/common/pre.js +156 -0
  38. package/client/common/promise-timeout.js +27 -0
  39. package/client/common/resolve.js +31 -0
  40. package/client/common/run-idle.js +1 -0
  41. package/client/common/safe-local-storage.js +35 -0
  42. package/client/common/safe-name.js +19 -0
  43. package/client/common/sftp.js +74 -0
  44. package/client/common/terminal-theme.js +158 -0
  45. package/client/common/test-connection.js +12 -0
  46. package/client/common/time.js +30 -0
  47. package/client/common/to-simple-obj.js +5 -0
  48. package/client/common/track.js +7 -0
  49. package/client/common/transfer.js +76 -0
  50. package/client/common/trzsz.js +62 -0
  51. package/client/common/ui-theme.js +44 -0
  52. package/client/common/uid.js +5 -0
  53. package/client/common/update-check.js +79 -0
  54. package/client/common/upgrade.js +68 -0
  55. package/client/common/wait.js +8 -0
  56. package/client/common/ws.js +161 -0
  57. package/client/components/batch-op/batch-op.jsx +650 -0
  58. package/client/components/bookmark-form/bookmark-form.styl +8 -0
  59. package/client/components/bookmark-form/bookmark-group-tree-format.js +39 -0
  60. package/client/components/bookmark-form/encodes.js +44 -0
  61. package/client/components/bookmark-form/form-ssh-common.jsx +208 -0
  62. package/client/components/bookmark-form/form-tabs.jsx +69 -0
  63. package/client/components/bookmark-form/index.jsx +159 -0
  64. package/client/components/bookmark-form/local-form-ui.jsx +152 -0
  65. package/client/components/bookmark-form/local-form.jsx +16 -0
  66. package/client/components/bookmark-form/proxy.jsx +49 -0
  67. package/client/components/bookmark-form/quick-command-list.jsx +31 -0
  68. package/client/components/bookmark-form/quick-command.jsx +228 -0
  69. package/client/components/bookmark-form/render-auth-ssh.jsx +104 -0
  70. package/client/components/bookmark-form/render-connection-hopping.jsx +229 -0
  71. package/client/components/bookmark-form/render-delayed-scripts.jsx +88 -0
  72. package/client/components/bookmark-form/render-ssh-tunnel.jsx +116 -0
  73. package/client/components/bookmark-form/serial-form-ui.jsx +311 -0
  74. package/client/components/bookmark-form/serial-form.jsx +20 -0
  75. package/client/components/bookmark-form/sftp-enable.jsx +33 -0
  76. package/client/components/bookmark-form/ssh-form-ui.jsx +100 -0
  77. package/client/components/bookmark-form/ssh-form.jsx +348 -0
  78. package/client/components/bookmark-form/telnet-form-ui.jsx +154 -0
  79. package/client/components/bookmark-form/telnet-form.jsx +16 -0
  80. package/client/components/bookmark-form/tree-delete.jsx +87 -0
  81. package/client/components/bookmark-form/use-form-funcs.jsx +50 -0
  82. package/client/components/bookmark-form/use-quick-commands.jsx +83 -0
  83. package/client/components/bookmark-form/use-submit.jsx +77 -0
  84. package/client/components/bookmark-form/use-ui.jsx +82 -0
  85. package/client/components/bookmark-form/x11.jsx +23 -0
  86. package/client/components/common/animate-text.jsx +37 -0
  87. package/client/components/common/animate-text.styl +54 -0
  88. package/client/components/common/external-link.jsx +28 -0
  89. package/client/components/common/help-icon.jsx +25 -0
  90. package/client/components/common/highlight.jsx +23 -0
  91. package/client/components/common/highlight.styl +3 -0
  92. package/client/components/common/input-auto-focus.jsx +68 -0
  93. package/client/components/common/input-confirm.jsx +66 -0
  94. package/client/components/common/logo-elem.jsx +22 -0
  95. package/client/components/common/markdown.jsx +27 -0
  96. package/client/components/common/react-subx.jsx +1 -0
  97. package/client/components/common/resize-wrap.jsx +222 -0
  98. package/client/components/common/resize-wrap.styl +9 -0
  99. package/client/components/common/search.jsx +9 -0
  100. package/client/components/common/show-item.jsx +27 -0
  101. package/client/components/context-menu/boomarks.jsx +15 -0
  102. package/client/components/context-menu/context-menu.jsx +340 -0
  103. package/client/components/context-menu/context-menu.styl +90 -0
  104. package/client/components/context-menu/history.jsx +27 -0
  105. package/client/components/context-menu/icon-holder.jsx +5 -0
  106. package/client/components/context-menu/menu-btn.jsx +224 -0
  107. package/client/components/context-menu/sub-tab-menu.jsx +23 -0
  108. package/client/components/context-menu/tabs.jsx +22 -0
  109. package/client/components/context-menu/zoom.jsx +40 -0
  110. package/client/components/footer/batch-input.jsx +177 -0
  111. package/client/components/footer/footer-entry.jsx +141 -0
  112. package/client/components/footer/footer.styl +47 -0
  113. package/client/components/icons/match-case.jsx +10 -0
  114. package/client/components/icons/match-whole-word.jsx +13 -0
  115. package/client/components/icons/regular-exp.jsx +10 -0
  116. package/client/components/main/css-overwrite.jsx +92 -0
  117. package/client/components/main/error-wrapper.jsx +59 -0
  118. package/client/components/main/index.jsx +11 -0
  119. package/client/components/main/loading.jsx +25 -0
  120. package/client/components/main/main.jsx +149 -0
  121. package/client/components/main/term-fullscreen-control.jsx +21 -0
  122. package/client/components/main/term-fullscreen.styl +27 -0
  123. package/client/components/main/ui-theme.jsx +31 -0
  124. package/client/components/main/upgrade.jsx +351 -0
  125. package/client/components/main/upgrade.styl +27 -0
  126. package/client/components/main/wrapper.styl +41 -0
  127. package/client/components/quick-commands/qm.styl +29 -0
  128. package/client/components/quick-commands/quick-command-item.jsx +36 -0
  129. package/client/components/quick-commands/quick-command-transport-mod.jsx +54 -0
  130. package/client/components/quick-commands/quick-command-transport.jsx +12 -0
  131. package/client/components/quick-commands/quick-commands-box.jsx +233 -0
  132. package/client/components/quick-commands/quick-commands-form-elem.jsx +119 -0
  133. package/client/components/quick-commands/quick-commands-form.jsx +33 -0
  134. package/client/components/quick-commands/quick-commands-list.jsx +128 -0
  135. package/client/components/quick-commands/quick-commands-select.jsx +38 -0
  136. package/client/components/session/session.jsx +533 -0
  137. package/client/components/session/session.styl +53 -0
  138. package/client/components/session/sessions.jsx +445 -0
  139. package/client/components/setting-panel/bookmark-transport.jsx +148 -0
  140. package/client/components/setting-panel/bookmark-tree-list.jsx +14 -0
  141. package/client/components/setting-panel/col.jsx +18 -0
  142. package/client/components/setting-panel/list.jsx +186 -0
  143. package/client/components/setting-panel/list.styl +33 -0
  144. package/client/components/setting-panel/on-tree-drop.js +222 -0
  145. package/client/components/setting-panel/setting-modal.jsx +163 -0
  146. package/client/components/setting-panel/setting-wrap.jsx +37 -0
  147. package/client/components/setting-panel/setting-wrap.styl +52 -0
  148. package/client/components/setting-panel/setting.jsx +858 -0
  149. package/client/components/setting-panel/setting.styl +4 -0
  150. package/client/components/setting-panel/start-session-select.jsx +91 -0
  151. package/client/components/setting-panel/tab-bookmarks.jsx +37 -0
  152. package/client/components/setting-panel/tab-history.jsx +44 -0
  153. package/client/components/setting-panel/tab-quick-commands.jsx +38 -0
  154. package/client/components/setting-panel/tab-settings.jsx +42 -0
  155. package/client/components/setting-panel/tab-themes.jsx +34 -0
  156. package/client/components/setting-panel/tree-list.jsx +978 -0
  157. package/client/components/setting-panel/tree-list.styl +57 -0
  158. package/client/components/setting-sync/data-import.jsx +65 -0
  159. package/client/components/setting-sync/setting-sync-form.jsx +271 -0
  160. package/client/components/setting-sync/setting-sync.jsx +81 -0
  161. package/client/components/setting-sync/sync.styl +7 -0
  162. package/client/components/sftp/address-bar.jsx +139 -0
  163. package/client/components/sftp/address-bookmark-item.jsx +47 -0
  164. package/client/components/sftp/address-bookmark.jsx +81 -0
  165. package/client/components/sftp/address-bookmark.styl +8 -0
  166. package/client/components/sftp/confirm-modal.jsx +184 -0
  167. package/client/components/sftp/file-icon.jsx +22 -0
  168. package/client/components/sftp/file-item.jsx +1226 -0
  169. package/client/components/sftp/file-mode-modal.jsx +205 -0
  170. package/client/components/sftp/file-props-modal.jsx +211 -0
  171. package/client/components/sftp/file-read.js +81 -0
  172. package/client/components/sftp/list-table-ui.jsx +547 -0
  173. package/client/components/sftp/owner-list.js +97 -0
  174. package/client/components/sftp/paged-list.jsx +60 -0
  175. package/client/components/sftp/permission-render.jsx +42 -0
  176. package/client/components/sftp/sftp-entry.jsx +1069 -0
  177. package/client/components/sftp/sftp.styl +217 -0
  178. package/client/components/sftp/transfer-common.js +9 -0
  179. package/client/components/sftp/transfer-conflict.jsx +315 -0
  180. package/client/components/sftp/transfer-speed-format.js +60 -0
  181. package/client/components/sftp/transfer-tag.jsx +40 -0
  182. package/client/components/sftp/transfer-tag.styl +11 -0
  183. package/client/components/sftp/transfer.styl +55 -0
  184. package/client/components/sftp/transport-action.jsx +410 -0
  185. package/client/components/sftp/transport-entry.jsx +108 -0
  186. package/client/components/sftp/transport-types.js +8 -0
  187. package/client/components/sftp/transports-action.jsx +111 -0
  188. package/client/components/sftp/transports-ui.jsx +93 -0
  189. package/client/components/sftp/zip.js +42 -0
  190. package/client/components/sidebar/bookmark-select.jsx +48 -0
  191. package/client/components/sidebar/bookmark.jsx +82 -0
  192. package/client/components/sidebar/history.jsx +66 -0
  193. package/client/components/sidebar/index.jsx +230 -0
  194. package/client/components/sidebar/info-modal.jsx +250 -0
  195. package/client/components/sidebar/info.styl +27 -0
  196. package/client/components/sidebar/side-icon.jsx +25 -0
  197. package/client/components/sidebar/sidebar.styl +128 -0
  198. package/client/components/sidebar/transfer-history-modal.jsx +110 -0
  199. package/client/components/sidebar/transfer-history.styl +3 -0
  200. package/client/components/sidebar/transfer-list-control.jsx +205 -0
  201. package/client/components/sidebar/transfer-list.jsx +55 -0
  202. package/client/components/sidebar/transfer-modal.jsx +76 -0
  203. package/client/components/sidebar/transfer.styl +8 -0
  204. package/client/components/sidebar/transport-ui.jsx +109 -0
  205. package/client/components/tabs/index.jsx +320 -0
  206. package/client/components/tabs/tab.jsx +427 -0
  207. package/client/components/tabs/tabs.styl +220 -0
  208. package/client/components/tabs/window-control.jsx +55 -0
  209. package/client/components/terminal/attach-addon-custom.js +70 -0
  210. package/client/components/terminal/build-ls-term-id.js +5 -0
  211. package/client/components/terminal/index.jsx +1358 -0
  212. package/client/components/terminal/normal-buffer.jsx +33 -0
  213. package/client/components/terminal/term-search.jsx +224 -0
  214. package/client/components/terminal/term-search.styl +15 -0
  215. package/client/components/terminal/terminal-apis.js +31 -0
  216. package/client/components/terminal/terminal-interactive.jsx +148 -0
  217. package/client/components/terminal/terminal.styl +96 -0
  218. package/client/components/terminal/xterm-zmodem.js +48 -0
  219. package/client/components/terminal/zmodem-transfer.jsx +98 -0
  220. package/client/components/terminal/zmodem.styl +14 -0
  221. package/client/components/terminal-info/activity.jsx +54 -0
  222. package/client/components/terminal-info/base.jsx +25 -0
  223. package/client/components/terminal-info/content.jsx +101 -0
  224. package/client/components/terminal-info/data-cols-parser.jsx +50 -0
  225. package/client/components/terminal-info/disk.jsx +29 -0
  226. package/client/components/terminal-info/index.jsx +25 -0
  227. package/client/components/terminal-info/network.jsx +114 -0
  228. package/client/components/terminal-info/resource.jsx +80 -0
  229. package/client/components/terminal-info/run-cmd.jsx +273 -0
  230. package/client/components/terminal-info/terminal-info.styl +29 -0
  231. package/client/components/terminal-info/up.jsx +15 -0
  232. package/client/components/terminal-theme/index.jsx +264 -0
  233. package/client/components/terminal-theme/terminal-theme-list.styl +3 -0
  234. package/client/components/terminal-theme/theme-list.jsx +146 -0
  235. package/client/components/text-editor/text-editor-form.jsx +97 -0
  236. package/client/components/text-editor/text-editor.jsx +182 -0
  237. package/client/css/antd-overwrite.styl +14 -0
  238. package/client/css/basic.styl +38 -0
  239. package/client/css/includes/box.styl +154 -0
  240. package/client/css/includes/font-size.styl +6 -0
  241. package/client/css/includes/index.styl +3 -0
  242. package/client/css/includes/text.styl +31 -0
  243. package/client/css/includes/theme-default.styl +20 -0
  244. package/client/entry/basic.js +58 -0
  245. package/client/entry/index.jsx +15 -0
  246. package/client/entry/worker.js +137 -0
  247. package/client/store/address-bookmark.js +25 -0
  248. package/client/store/app-upgrade.js +23 -0
  249. package/client/store/batch-input-history.js +26 -0
  250. package/client/store/bookmark-group.js +128 -0
  251. package/client/store/bookmark.js +22 -0
  252. package/client/store/common.js +140 -0
  253. package/client/store/context-menu.js +23 -0
  254. package/client/store/db-upgrade.js +43 -0
  255. package/client/store/event.js +70 -0
  256. package/client/store/index.js +335 -0
  257. package/client/store/init-state.js +191 -0
  258. package/client/store/item.js +120 -0
  259. package/client/store/load-data.js +198 -0
  260. package/client/store/quick-command.js +43 -0
  261. package/client/store/session.js +54 -0
  262. package/client/store/setting.js +208 -0
  263. package/client/store/sidebar.js +48 -0
  264. package/client/store/sync.js +390 -0
  265. package/client/store/system-menu.js +120 -0
  266. package/client/store/tab.js +74 -0
  267. package/client/store/terminal-theme.js +116 -0
  268. package/client/store/transfer-history.js +27 -0
  269. package/client/store/transfer-list.js +20 -0
  270. package/client/store/ui-theme.js +71 -0
  271. package/client/store/watch.js +116 -0
  272. package/client/views/index.pug +58 -0
  273. package/package.json +34 -0
@@ -0,0 +1,858 @@
1
+ import React, { Component } from 'react'
2
+ import { CodeOutlined, LoadingOutlined } from '@ant-design/icons'
3
+ import {
4
+ message,
5
+ Select,
6
+ Switch,
7
+ Input,
8
+ Upload,
9
+ InputNumber,
10
+ Alert,
11
+ Button,
12
+ AutoComplete,
13
+ Tooltip,
14
+ Table,
15
+ Space
16
+ } from 'antd'
17
+ import deepCopy from 'json-deep-copy'
18
+ import {
19
+ noTerminalBgValue,
20
+ settingMap,
21
+ rendererTypes,
22
+ proxyHelpLink,
23
+ isWin
24
+ } from '../../common/constants'
25
+ import defaultSettings from '../../../app/common/default-setting'
26
+ import ShowItem from '../common/show-item'
27
+ import { osResolve } from '../../common/resolve'
28
+ import Link from '../common/external-link'
29
+ import { isNumber, isNaN } from 'lodash-es'
30
+ import createEditLangLink from '../../common/create-lang-edit-link'
31
+ import mapper from '../../common/auto-complete-data-mapper'
32
+ import StartSession from './start-session-select'
33
+ import HelpIcon from '../common/help-icon'
34
+ import fs from '../../common/fs'
35
+ import './setting.styl'
36
+
37
+ const { Option } = Select
38
+ const { prefix } = window
39
+ const e = prefix('setting')
40
+ const f = prefix('form')
41
+ const s = prefix('ssh')
42
+ const p = prefix('sftp')
43
+ const t = prefix('terminalThemes')
44
+
45
+ const modifiers = [
46
+ 'Command',
47
+ 'Control',
48
+ 'Alt',
49
+ 'Shift'
50
+ ]
51
+ const keys = [
52
+ ...'0123456789~ABCDEFGHIJKLMNOPQRTSUVWXYZ'.split(''),
53
+ ...new Array(12).fill(0).map((m, i) => {
54
+ return 'F' + (i + 1)
55
+ })
56
+ ]
57
+
58
+ export default class Setting extends Component {
59
+ state = {
60
+ ready: false,
61
+ languageChanged: false
62
+ }
63
+
64
+ componentDidMount () {
65
+ this.timer = setTimeout(() => {
66
+ this.setState({
67
+ ready: true
68
+ })
69
+ }, 200)
70
+ }
71
+
72
+ componentWillUnmount () {
73
+ clearTimeout(this.timer)
74
+ }
75
+
76
+ handleRestart = () => {
77
+ window.location.reload()
78
+ }
79
+
80
+ handleResetAll = () => {
81
+ this.saveConfig(
82
+ deepCopy(defaultSettings)
83
+ )
84
+ }
85
+
86
+ handleChangeModifier = modifier => {
87
+ const { hotkey } = this.props.config
88
+ const key = hotkey.split('+')[1]
89
+ return this.saveConfig({
90
+ hotkey: `${modifier}+${key}`
91
+ })
92
+ }
93
+
94
+ onChangeTimeout = sshReadyTimeout => {
95
+ return this.saveConfig({
96
+ sshReadyTimeout
97
+ })
98
+ }
99
+
100
+ handleChangeKey = key => {
101
+ const { hotkey } = this.props.config
102
+ const modifier = hotkey.split('+')[0]
103
+ return this.saveConfig({
104
+ hotkey: `${modifier}+${key}`
105
+ })
106
+ }
107
+
108
+ handleChangeLang = language => {
109
+ this.setState({
110
+ languageChanged: true
111
+ })
112
+ return this.saveConfig({
113
+ language
114
+ })
115
+ }
116
+
117
+ handleChangeTerminalTheme = id => {
118
+ this.props.store.setTheme(id)
119
+ }
120
+
121
+ onChangeValue = (value, name) => {
122
+ if (name === 'useSystemTitleBar') {
123
+ message.info(e('useSystemTitleBarTip'), 5)
124
+ }
125
+ this.saveConfig({
126
+ [name]: value
127
+ })
128
+ }
129
+
130
+ onChangeStartSessions = value => {
131
+ this.onChangeValue(value, 'onStartSessions')
132
+ }
133
+
134
+ handleChangeFont = (values) => {
135
+ this.onChangeValue(
136
+ values.join(', '),
137
+ 'fontFamily'
138
+ )
139
+ }
140
+
141
+ handleChangeCursorStyle = (cursorStyle) => {
142
+ this.onChangeValue(
143
+ cursorStyle,
144
+ 'cursorStyle'
145
+ )
146
+ }
147
+
148
+ saveConfig = async (_ext) => {
149
+ const config = deepCopy(this.props.config)
150
+ const ext = deepCopy(_ext)
151
+ const update = Object.assign({}, config, deepCopy(_ext))
152
+ if (ext.hotkey && ext.hotkey !== config.hotkey) {
153
+ const res = await window.pre.runGlobalAsync('changeHotkey', ext.hotkey)
154
+ if (!res) {
155
+ message.warning(e('hotkeyNotOk'))
156
+ update.config.hotkey = config.hotkey
157
+ ext.hotkey = config.hotkey
158
+ } else {
159
+ message.success(e('saved'))
160
+ }
161
+ }
162
+ this.props.store.setConfig(update)
163
+ }
164
+
165
+ renderOption = (m, i) => {
166
+ return (
167
+ <Option value={m} key={m + 'opt' + i}>{m}</Option>
168
+ )
169
+ }
170
+
171
+ renderToggle = (name, extra = null) => {
172
+ const checked = !!this.props.config[name]
173
+ return (
174
+ <div className='pd2b' key={'rt' + name}>
175
+ <Switch
176
+ checked={checked}
177
+ checkedChildren={e(name)}
178
+ unCheckedChildren={e(name)}
179
+ onChange={v => this.onChangeValue(v, name)}
180
+ />
181
+ {isNumber(extra) ? null : extra}
182
+ </div>
183
+ )
184
+ }
185
+
186
+ renderLanguageChangeTip = () => {
187
+ if (!this.state.languageChanged) {
188
+ return null
189
+ }
190
+ return (
191
+ <div className='pd1t'>
192
+ <Alert
193
+ message={
194
+ <div>
195
+ {e('saveLang')}
196
+ <Button
197
+ onClick={this.handleRestart}
198
+ className='mg1l'
199
+ >
200
+ {e('restartNow')}
201
+ </Button>
202
+ </div>
203
+ }
204
+ type='success'
205
+ />
206
+ </div>
207
+ )
208
+ }
209
+
210
+ renderNumber = (name, options, title = '', width = 136) => {
211
+ let value = this.props.config[name]
212
+ if (options.valueParser) {
213
+ value = options.valueParser(value)
214
+ }
215
+ const defaultValue = defaultSettings[name]
216
+ const {
217
+ step = 1,
218
+ min,
219
+ max,
220
+ cls,
221
+ onChange = (v) => {
222
+ this.onChangeValue(v, name)
223
+ }
224
+ } = options
225
+ const opts = {
226
+ step,
227
+ value,
228
+ min,
229
+ max,
230
+ onChange,
231
+ placeholder: defaultValue
232
+ }
233
+ if (title) {
234
+ opts.formatter = v => `${title}${options.extraDesc || ''}: ${v}`
235
+ opts.parser = (v) => {
236
+ let vv = isNumber(v)
237
+ ? v
238
+ : Number(v.split(': ')[1], 10)
239
+ if (isNaN(vv)) {
240
+ vv = defaultValue
241
+ }
242
+ return vv
243
+ }
244
+ opts.style = {
245
+ width: width + 'px'
246
+ }
247
+ }
248
+ return (
249
+ <div className={`pd2b ${cls || ''}`}>
250
+ <InputNumber
251
+ {...opts}
252
+ />
253
+ </div>
254
+ )
255
+ }
256
+
257
+ renderText = (name, placeholder) => {
258
+ const value = this.props.config[name]
259
+ const defaultValue = defaultSettings[name]
260
+ const onChange = (e) => this.onChangeValue(e.target.value, name)
261
+ return (
262
+ <div className='pd2b'>
263
+ <Input
264
+ value={value}
265
+ onChange={onChange}
266
+ placeholder={placeholder || defaultValue}
267
+ />
268
+ </div>
269
+ )
270
+ }
271
+
272
+ renderTextExec = (name) => {
273
+ const agrsProp = `${name}Args`
274
+ const args = this.props.config[agrsProp]
275
+ const value = this.props.config[name]
276
+ const defaultValue = defaultSettings[name]
277
+ const onChange = (e) => this.onChangeValue(e.target.value, name)
278
+ const onChangeArgs = (v) => this.onChangeValue(v, agrsProp)
279
+ const style = {
280
+ style: {
281
+ width: '40%'
282
+ }
283
+ }
284
+ const styleArg = {
285
+ style: {
286
+ width: '40%',
287
+ marginLeft: '3px'
288
+ }
289
+ }
290
+ return (
291
+ <div className='pd2b'>
292
+ <Space.Compact>
293
+ <Input
294
+ value={value}
295
+ {...style}
296
+ onChange={onChange}
297
+ placeholder={defaultValue}
298
+ />
299
+ <Select
300
+ {...styleArg}
301
+ placeholder='args'
302
+ onChange={onChangeArgs}
303
+ value={args}
304
+ mode='tags'
305
+ >
306
+ {
307
+ args.map((arg, i) => {
308
+ return (
309
+ <Option key={arg + '__' + i} value={arg}>
310
+ {arg}
311
+ </Option>
312
+ )
313
+ })
314
+ }
315
+ </Select>
316
+ </Space.Compact>
317
+ </div>
318
+ )
319
+ }
320
+
321
+ renderBgOption = item => {
322
+ return {
323
+ value: item.value,
324
+ label: item.desc
325
+ }
326
+ }
327
+
328
+ renderTerminalBgSelect = (name) => {
329
+ const value = this.props.config[name]
330
+ const defaultValue = defaultSettings[name]
331
+ const onChange = (v) => this.onChangeValue(v, name)
332
+ const after = (
333
+ <Upload
334
+ beforeUpload={(file) => {
335
+ this.onChangeValue(file.path, name)
336
+ return false
337
+ }}
338
+ showUploadList={false}
339
+ >
340
+ <span>{e('chooseFile')}</span>
341
+ </Upload>
342
+ )
343
+ const dataSource = [
344
+ {
345
+ value: '',
346
+ desc: t('default')
347
+ },
348
+ {
349
+ value: noTerminalBgValue,
350
+ desc: e('noTerminalBg')
351
+ }
352
+ ]
353
+ const numberOpts = { step: 0.05, min: 0, max: 1, cls: 'bg-img-setting' }
354
+
355
+ const renderFilter = () => {
356
+ if (this.props.config[name] === noTerminalBgValue) return
357
+
358
+ return (
359
+ <div>
360
+ {
361
+ this.renderNumber(
362
+ 'terminalBackgroundFilterOpacity',
363
+ numberOpts,
364
+ e('Opacity')
365
+ )
366
+ }
367
+ {
368
+ this.renderNumber(
369
+ 'terminalBackgroundFilterBlur',
370
+ { ...numberOpts, min: 0, max: 50, step: 0.5 },
371
+ e('Blur')
372
+ )
373
+ }
374
+ {
375
+ this.renderNumber(
376
+ 'terminalBackgroundFilterBrightness',
377
+ { ...numberOpts, min: 0, max: 10, step: 0.1 },
378
+ e('Brightness')
379
+ )
380
+ }
381
+ {
382
+ this.renderNumber(
383
+ 'terminalBackgroundFilterGrayscale',
384
+ numberOpts,
385
+ e('Grayscale')
386
+ )
387
+ }
388
+ {
389
+ this.renderNumber(
390
+ 'terminalBackgroundFilterContrast',
391
+ { ...numberOpts, min: 0, max: 10, step: 0.1 },
392
+ e('Contrast')
393
+ )
394
+ }
395
+ </div>
396
+ )
397
+ }
398
+
399
+ return (
400
+ <div className='pd2b'>
401
+ <div className='pd1b'>
402
+ <Tooltip
403
+ title='eg: https://xx.com/xx.png or /path/to/xx.png'
404
+ >
405
+ <AutoComplete
406
+ value={value}
407
+ onChange={onChange}
408
+ placeholder={defaultValue}
409
+ className='width-100'
410
+ options={dataSource.map(this.renderBgOption)}
411
+ >
412
+ <Input
413
+ addonAfter={after}
414
+ />
415
+ </AutoComplete>
416
+ </Tooltip>
417
+ </div>
418
+
419
+ {
420
+ renderFilter()
421
+ }
422
+ </div>
423
+ )
424
+ }
425
+
426
+ renderReset = () => {
427
+ return (
428
+ <div className='pd1b pd1t'>
429
+ <Button
430
+ onClick={this.handleResetAll}
431
+ >
432
+ {e('resetAllToDefault')}
433
+ </Button>
434
+ </div>
435
+ )
436
+ }
437
+
438
+ renderDefaultTerminalType = () => {
439
+ const opts = this.props.config.terminalTypes.map(mapper)
440
+ return (
441
+ <AutoComplete
442
+ options={opts}
443
+ style={{
444
+ width: '200px'
445
+ }}
446
+ value={this.props.config.terminalType}
447
+ onChange={(v) => this.onChangeValue(v, 'terminalType')}
448
+ />
449
+ )
450
+ }
451
+
452
+ renderProxy () {
453
+ const {
454
+ enableGlobalProxy
455
+ } = this.props.config
456
+ const helps = `http# http://proxy-server-over-tcp.com:3128
457
+ https#https://proxy-server-over-tls.com:3129
458
+ socks(v5)#socks://username:password@some-socks-proxy.com:9050 (username & password are optional)
459
+ socks5#socks5://username:password@some-socks-proxy.com:9050 (username & password are optional)
460
+ socks5h#socks5h://username:password@some-socks-proxy.com:9050 (username & password are optional)
461
+ socks4#socks4://some-socks-proxy.com:9050
462
+ socks4a#socks4a://some-socks-proxy.com:9050`
463
+ .split('\n')
464
+ .filter(d => d.trim())
465
+ .map(d => {
466
+ const [protocol, example] = d.split('#')
467
+ return {
468
+ protocol, example
469
+ }
470
+ })
471
+ const cols = Object.keys(helps[0]).map(k => {
472
+ return {
473
+ title: k,
474
+ dataIndex: k,
475
+ key: k,
476
+ render: (k) => k || ''
477
+ }
478
+ })
479
+ const table = (
480
+ <div>
481
+ <Table
482
+ columns={cols}
483
+ dataSource={helps}
484
+ bordered
485
+ pagination={false}
486
+ size='small'
487
+ rowKey='protocol'
488
+ />
489
+ <div>
490
+ <Link to={proxyHelpLink}>{proxyHelpLink}</Link>
491
+ </div>
492
+ </div>
493
+ )
494
+ const style = {
495
+ height: '414px',
496
+ width: '500px'
497
+ }
498
+ return (
499
+ <div className='pd1b'>
500
+ <div className='pd1b'>
501
+ <span className='pd1r'>
502
+ {e('global')} {f('proxy')}
503
+ <HelpIcon
504
+ title={table}
505
+ overlayInnerStyle={style}
506
+ />
507
+ </span>
508
+ <Switch
509
+ checked={enableGlobalProxy}
510
+ onChange={v => {
511
+ this.onChangeValue(v, 'enableGlobalProxy')
512
+ }}
513
+ />
514
+ </div>
515
+ {
516
+ this.renderText('proxy', 'socks5://127.0.0.1:1080')
517
+ }
518
+ </div>
519
+ )
520
+ }
521
+
522
+ renderCursorStyleSelect = () => {
523
+ const {
524
+ cursorStyle = 'block'
525
+ } = this.props.config
526
+ const sets = [
527
+ {
528
+ id: 'block',
529
+ title: '▊'
530
+ },
531
+ {
532
+ id: 'underline',
533
+ title: '_'
534
+ },
535
+ {
536
+ id: 'bar',
537
+ title: '|'
538
+ }
539
+ ]
540
+ const props = {
541
+ onChange: this.handleChangeCursorStyle,
542
+ value: cursorStyle,
543
+ style: {
544
+ width: '100px'
545
+ }
546
+ }
547
+ return (
548
+ <div className='pd1b'>
549
+ <span className='inline-title mg1r'>{e('cursorStyle')}</span>
550
+ <Select
551
+ {...props}
552
+ showSearch
553
+ >
554
+ {
555
+ sets.map(f => {
556
+ return (
557
+ <Option value={f.id} key={f.id}>
558
+ <b>{f.title}</b>
559
+ </Option>
560
+ )
561
+ })
562
+ }
563
+ </Select>
564
+ </div>
565
+ )
566
+ }
567
+
568
+ renderFontFamily = () => {
569
+ const { fonts } = this.props.store
570
+ const { fontFamily } = this.props.config
571
+ const props = {
572
+ mode: 'multiple',
573
+ onChange: this.handleChangeFont,
574
+ value: fontFamily.split(/, */g)
575
+ }
576
+ return (
577
+ <Select
578
+ {...props}
579
+ showSearch
580
+ >
581
+ {
582
+ fonts.map(f => {
583
+ return (
584
+ <Option value={f} key={f}>
585
+ <span style={{
586
+ fontFamily: f
587
+ }}
588
+ >{f}
589
+ </span>
590
+ </Option>
591
+ )
592
+ })
593
+ }
594
+ </Select>
595
+ )
596
+ }
597
+
598
+ handlePortable = async () => {
599
+ const {
600
+ appPath,
601
+ exePath
602
+ } = this.props.store
603
+ const from = osResolve(appPath, 'electerm', 'users')
604
+ const tar = osResolve(exePath, 'electerm', 'users')
605
+ const cmd = `xcopy /E /I /Q /Y "${from}" ${tar}`
606
+ const x = await fs.runWinCmd(cmd)
607
+ .catch(err => {
608
+ this.props.store.onError(err)
609
+ return false
610
+ })
611
+ if (x !== false) {
612
+ message.success(
613
+ `${e('dataTransferedTo')}: ${tar}`
614
+ )
615
+ setTimeout(
616
+ this.props.store.restart, 5000
617
+ )
618
+ }
619
+ }
620
+
621
+ renderMakePortable () {
622
+ const {
623
+ isPortable
624
+ } = this.props.store
625
+ if (!isWin || isPortable) {
626
+ return null
627
+ }
628
+ return (
629
+ <div className='pd1y'>
630
+ <Button
631
+ onClick={this.handlePortable}
632
+ >
633
+ {e('makeItPortable')}
634
+ </Button>
635
+ </div>
636
+ )
637
+ }
638
+
639
+ render () {
640
+ const { ready } = this.state
641
+ if (!ready) {
642
+ return (
643
+ <div className='pd3 aligncenter'>
644
+ <LoadingOutlined />
645
+ </div>
646
+ )
647
+ }
648
+ const {
649
+ hotkey,
650
+ language,
651
+ rendererType,
652
+ theme
653
+ } = this.props.config
654
+ const {
655
+ appPath,
656
+ langs
657
+ } = this.props.store
658
+ const terminalLogPath = osResolve(appPath, 'electerm', 'session_logs')
659
+ const terminalThemes = this.props.store.getSidebarList(settingMap.terminalThemes)
660
+ const [modifier, key] = hotkey.split('+')
661
+ const pops = {
662
+ onStartSessions: this.props.config.onStartSessions,
663
+ store: this.props.store,
664
+ onChangeStartSessions: this.onChangeStartSessions
665
+ }
666
+ return (
667
+ <div className='form-wrap pd1y pd2x'>
668
+ <h2>{e('settings')}</h2>
669
+ <div className='pd1b'>{e('hotkeyDesc')}</div>
670
+ <div className='pd2b'>
671
+ <Select
672
+ value={modifier}
673
+ onChange={this.handleChangeModifier}
674
+ className='iblock width100'
675
+ popupMatchSelectWidth={false}
676
+ showSearch
677
+ >
678
+ {
679
+ modifiers.map(this.renderOption)
680
+ }
681
+ </Select>
682
+ <span className='iblock mg1x'>+</span>
683
+ <Select
684
+ value={key}
685
+ className='iblock width100'
686
+ onChange={this.handleChangeKey}
687
+ popupMatchSelectWidth={false}
688
+ showSearch
689
+ >
690
+ {
691
+ keys.map(this.renderOption)
692
+ }
693
+ </Select>
694
+ </div>
695
+ <div className='pd1b'>{e('onStartBookmarks')}</div>
696
+ <div className='pd2b'>
697
+ <StartSession
698
+ {...pops}
699
+ />
700
+ </div>
701
+ {this.renderProxy()}
702
+ {
703
+ this.renderNumber('scrollback', {
704
+ step: 200,
705
+ min: 1000
706
+ }, e('scrollBackDesc'), 400)
707
+ }
708
+ {
709
+ this.renderNumber('sshReadyTimeout', {
710
+ step: 200,
711
+ min: 100,
712
+ cls: 'timeout-desc'
713
+ }, e('timeoutDesc'), 400)
714
+ }
715
+ {
716
+ this.renderNumber('keepaliveInterval', {
717
+ step: 1000,
718
+ min: 0,
719
+ max: 20000000,
720
+ cls: 'keepalive-interval-desc',
721
+ extraDesc: '(ms)'
722
+ }, e('keepaliveIntervalDesc'), 400)
723
+ }
724
+ {
725
+ this.renderNumber('opacity', {
726
+ step: 0.05,
727
+ min: 0,
728
+ max: 1,
729
+ cls: 'opacity'
730
+ }, e('opacity'), 400)
731
+ }
732
+
733
+ <div className='pd2b'>
734
+ <span className='inline-title mg1r'>{e('terminalTheme')}</span>
735
+ <Select
736
+ onChange={this.handleChangeTerminalTheme}
737
+ popupMatchSelectWidth={false}
738
+ value={theme}
739
+ >
740
+ {
741
+ terminalThemes.map(l => {
742
+ const { id, name } = l
743
+ return (
744
+ <Option key={id} value={id}>{name}</Option>
745
+ )
746
+ })
747
+ }
748
+ </Select>
749
+ </div>
750
+ <div className='pd2b'>
751
+ <span className='inline-title mg1r'>{e('language')}</span>
752
+ <Select
753
+ onChange={this.handleChangeLang}
754
+ value={language}
755
+ popupMatchSelectWidth={false}
756
+ >
757
+ {
758
+ langs.map(l => {
759
+ const { id, name } = l
760
+ return (
761
+ <Option key={id} value={id}>{name}</Option>
762
+ )
763
+ })
764
+ }
765
+ </Select>
766
+ <Link className='mg1l' to={createEditLangLink(language)}>{p('edit')}</Link>
767
+ </div>
768
+ {this.renderLanguageChangeTip()}
769
+ <div className='pd1y font16 bold'>
770
+ <CodeOutlined className='mg1r' />
771
+ {s('terminal')} {e('settings')}
772
+ </div>
773
+ <div className='pd2b'>
774
+ <span className='inline-title mg1r'>{e('rendererType')}</span>
775
+ <Select
776
+ onChange={v => this.onChangeValue(v, 'rendererType')}
777
+ value={rendererType}
778
+ popupMatchSelectWidth={false}
779
+ >
780
+ {
781
+ Object.keys(rendererTypes).map(id => {
782
+ return (
783
+ <Option key={id} value={id}>{id}</Option>
784
+ )
785
+ })
786
+ }
787
+ </Select>
788
+ </div>
789
+ {
790
+ this.renderNumber('fontSize', {
791
+ step: 1,
792
+ min: 9
793
+ }, `${t('default')} ${e('fontSize')}`, 400)
794
+ }
795
+ <div className='pd2b'>
796
+ <span className='inline-title mg1r'>{t('default')} {e('fontFamily')}</span>
797
+ {
798
+ this.renderFontFamily()
799
+ }
800
+ </div>
801
+ <div className='pd2b'>
802
+ <span className='inline-title mg1r'>{e('defaultTerminalType')}</span>
803
+ {
804
+ this.renderDefaultTerminalType()
805
+ }
806
+ </div>
807
+ <div className='pd1b'>{e('terminalBackgroundImage')}</div>
808
+ {
809
+ this.renderTerminalBgSelect('terminalBackgroundImagePath')
810
+ }
811
+ <div className='pd1b'>{t('default')} {e('editorTip')}</div>
812
+ {
813
+ this.renderText('defaultEditor', e('editorTip'))
814
+ }
815
+ <div className='pd1b'>{t('default')} {e('execWindows')}</div>
816
+ {
817
+ this.renderTextExec('execWindows')
818
+ }
819
+ <div className='pd1b'>{t('default')} {e('execMac')}</div>
820
+ {
821
+ this.renderTextExec('execMac')
822
+ }
823
+ <div className='pd1b'>{t('default')} {e('execLinux')}</div>
824
+ {
825
+ this.renderTextExec('execLinux')
826
+ }
827
+ {
828
+ this.renderCursorStyleSelect()
829
+ }
830
+ {
831
+ [
832
+ 'autoRefreshWhenSwitchToSftp',
833
+ 'screenReaderMode',
834
+ 'initDefaultTabOnStart',
835
+ 'cursorBlink',
836
+ 'rightClickSelectsWord',
837
+ 'pasteWhenContextMenu',
838
+ 'copyWhenSelect',
839
+ 'disableSshHistory',
840
+ 'disableTransferHistory',
841
+ 'ctrlOrMetaOpenTerminalLink',
842
+ 'checkUpdateOnStart',
843
+ 'useSystemTitleBar',
844
+ 'confirmBeforeExit',
845
+ 'debug'
846
+ ].map(this.renderToggle)
847
+ }
848
+ {this.renderToggle('saveTerminalLogToFile', (
849
+ <ShowItem to={terminalLogPath} className='mg1l'>{p('open')}</ShowItem>
850
+ ))}
851
+ {
852
+ this.renderMakePortable()
853
+ }
854
+ {this.renderReset()}
855
+ </div>
856
+ )
857
+ }
858
+ }