@electerm/electerm-react 5.3.26 → 5.5.6
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.
- package/README.md +246 -12
- package/client/common/choose-save-folder.js +21 -2
- package/client/common/constants.js +20 -6
- package/client/common/create-title.jsx +6 -0
- package/client/common/default-setting.js +14 -0
- package/client/common/init-setting-item.js +5 -0
- package/client/common/platform.js +24 -0
- package/client/components/ai/agent-tool-call-card.jsx +10 -2
- package/client/components/ai/agent.js +4 -1
- package/client/components/ai/ai-attachments.js +87 -0
- package/client/components/ai/ai-chat-empty.jsx +43 -0
- package/client/components/ai/ai-chat-entry.jsx +13 -4
- package/client/components/ai/ai-chat-history-item.jsx +28 -4
- package/client/components/ai/ai-chat-history.jsx +2 -1
- package/client/components/ai/ai-chat.jsx +104 -13
- package/client/components/ai/ai-config-props.js +4 -130
- package/client/components/ai/ai-config.jsx +135 -15
- package/client/components/ai/ai-presets.js +173 -0
- package/client/components/ai/ai.styl +83 -0
- package/client/components/bg/css-overwrite.jsx +11 -0
- package/client/components/bookmark-form/bookmark-schema.js +4 -0
- package/client/components/bookmark-form/common/fields.jsx +3 -0
- package/client/components/bookmark-form/config/common-fields.js +12 -0
- package/client/components/bookmark-form/config/local.js +3 -2
- package/client/components/bookmark-form/config/serial.js +3 -2
- package/client/components/bookmark-form/config/ssh.js +2 -1
- package/client/components/bookmark-form/config/telnet.js +3 -2
- package/client/components/common/item-filter.jsx +76 -0
- package/client/components/common/item-filter.styl +54 -0
- package/client/components/common/lazy-boundary.jsx +34 -0
- package/client/components/common/opacity.jsx +3 -1
- package/client/components/footer/footer-entry.jsx +35 -5
- package/client/components/footer/footer.styl +8 -1
- package/client/components/layout/layout.jsx +23 -31
- package/client/components/layout/pixed.js +3 -0
- package/client/components/main/main.jsx +55 -28
- package/client/components/main/term-fullscreen.styl +9 -3
- package/client/components/quick-commands/qm.styl +3 -2
- package/client/components/rdp/file-transfer.js +4 -4
- package/client/components/remote-monitor/monitor-details.jsx +458 -0
- package/client/components/remote-monitor/monitor-details.styl +87 -0
- package/client/components/remote-monitor/monitor-model.js +764 -0
- package/client/components/remote-monitor/remote-monitor-bar-entry.jsx +18 -0
- package/client/components/remote-monitor/remote-monitor-bar.jsx +344 -0
- package/client/components/remote-monitor/remote-monitor-bar.styl +106 -0
- package/client/components/remote-monitor/session-monitor.js +361 -0
- package/client/components/remote-monitor/use-monitor-details.js +10 -0
- package/client/components/remote-monitor/visibility.js +18 -0
- package/client/components/session/session-control.jsx +29 -2
- package/client/components/session/session.jsx +40 -18
- package/client/components/session/sessions.jsx +5 -2
- package/client/components/setting-panel/setting-common.jsx +25 -56
- package/client/components/setting-panel/setting-modal.jsx +57 -42
- package/client/components/setting-panel/setting-terminal.jsx +7 -2
- package/client/components/setting-panel/setting.styl +1 -1
- package/client/components/setting-panel/tab-triggers.jsx +71 -0
- package/client/components/sftp/file-compare-modal.jsx +6 -3
- package/client/components/sftp/file-item.jsx +5 -3
- package/client/components/sftp/owner-list.js +11 -2
- package/client/components/side-panel-r/side-panel-r.jsx +2 -2
- package/client/components/sys-menu/menu-btn.jsx +30 -1
- package/client/components/tabs/index.jsx +2 -2
- package/client/components/tabs/tab-title.jsx +3 -2
- package/client/components/tabs/tab.jsx +5 -1
- package/client/components/terminal/attach-addon-custom.js +295 -49
- package/client/components/terminal/automation/index.js +64 -0
- package/client/components/terminal/automation/keys.js +49 -0
- package/client/components/terminal/automation/stream-matcher.js +82 -0
- package/client/components/terminal/automation/strip-ansi.js +19 -0
- package/client/components/terminal/automation/trigger-engine.js +233 -0
- package/client/components/terminal/automation/trigger-presets.js +110 -0
- package/client/components/terminal/command-tracker-addon.js +31 -1
- package/client/components/terminal/mixins/index.js +27 -0
- package/client/components/terminal/mixins/term-attach.js +123 -0
- package/client/components/terminal/mixins/term-config.jsx +84 -0
- package/client/components/terminal/mixins/term-content.js +88 -0
- package/client/components/terminal/mixins/term-context-menu.jsx +291 -0
- package/client/components/terminal/mixins/term-file-drop.js +149 -0
- package/client/components/terminal/mixins/term-init.js +122 -0
- package/client/components/terminal/mixins/term-log.jsx +96 -0
- package/client/components/terminal/mixins/term-resize.js +87 -0
- package/client/components/terminal/mixins/term-socket.js +433 -0
- package/client/components/terminal/mixins/term-suggestions.js +224 -0
- package/client/components/terminal/mixins/term-theme.js +190 -0
- package/client/components/terminal/mixins/term-touch.js +136 -0
- package/client/components/terminal/shell-detect.js +37 -0
- package/client/components/terminal/shell.js +0 -28
- package/client/components/terminal/shortcut-bar-entry.jsx +6 -3
- package/client/components/terminal/shortcut-bar.jsx +4 -6
- package/client/components/terminal/shortcut-bar.styl +4 -0
- package/client/components/terminal/ssh-reload-state.js +56 -0
- package/client/components/terminal/startup-queue.js +379 -0
- package/client/components/terminal/terminal-interactive.jsx +32 -0
- package/client/components/terminal/terminal.jsx +102 -2007
- package/client/components/terminal/transfer-client-base.js +5 -29
- package/client/components/terminal/trzsz-client.js +1 -3
- package/client/components/terminal/xmodem-client.js +1 -3
- package/client/components/terminal/xterm-loader.js +7 -0
- package/client/components/terminal/zmodem-client.js +1 -3
- package/client/components/terminal-info/base.jsx +18 -70
- package/client/components/terminal-info/terminal-info-entry.jsx +13 -5
- package/client/components/terminal-info/terminal-info.jsx +50 -59
- package/client/components/terminal-info/terminal-info.styl +6 -49
- package/client/components/text-editor/open-text-editor.js +30 -0
- package/client/components/text-editor/text-editor-entry.jsx +17 -6
- package/client/components/text-editor/text-editor.jsx +14 -0
- package/client/components/triggers/trigger-editor.jsx +246 -0
- package/client/components/triggers/trigger-form.jsx +200 -0
- package/client/components/triggers/trigger-session-modal.jsx +199 -0
- package/client/components/triggers/trigger-setting-list.jsx +89 -0
- package/client/components/triggers/trigger-transport.jsx +60 -0
- package/client/components/triggers/triggers-field.jsx +19 -0
- package/client/components/widgets/widgets-list.jsx +11 -1
- package/client/css/mobile.styl +9 -1
- package/client/store/common.js +12 -1
- package/client/store/init-state.js +7 -0
- package/client/store/mcp-handler.js +158 -30
- package/client/store/setting.js +9 -0
- package/client/store/store.js +2 -0
- package/client/store/sync.js +2 -0
- package/client/store/tab.js +41 -3
- package/client/store/trigger.js +118 -0
- package/client/store/watch.js +13 -5
- package/client/views/index.pug +3 -0
- package/package.json +1 -1
- package/client/components/terminal-info/activity.jsx +0 -57
- package/client/components/terminal-info/data-cols-parser.jsx +0 -54
- package/client/components/terminal-info/disk.jsx +0 -45
- package/client/components/terminal-info/format-disks.js +0 -45
- package/client/components/terminal-info/network.jsx +0 -121
- package/client/components/terminal-info/resource.jsx +0 -99
- package/client/components/terminal-info/run-cmd.jsx +0 -263
- package/client/components/terminal-info/sys-info.jsx +0 -56
- package/client/components/terminal-info/up.jsx +0 -17
|
@@ -11,7 +11,6 @@ import SwitchLabel from '../common/switch'
|
|
|
11
11
|
import {
|
|
12
12
|
Select,
|
|
13
13
|
Button,
|
|
14
|
-
Table,
|
|
15
14
|
Space,
|
|
16
15
|
Tag
|
|
17
16
|
} from 'antd'
|
|
@@ -22,7 +21,8 @@ import InputNumberConfirm from '../common/input-number-confirm'
|
|
|
22
21
|
import TextareaConfirm from '../common/textarea-confirm'
|
|
23
22
|
import {
|
|
24
23
|
settingMap,
|
|
25
|
-
proxyHelpLink
|
|
24
|
+
proxyHelpLink,
|
|
25
|
+
webAppHiddenSettings
|
|
26
26
|
} from '../../common/constants'
|
|
27
27
|
import defaultSettings from '../../common/default-setting'
|
|
28
28
|
import Link from '../common/external-link'
|
|
@@ -320,56 +320,13 @@ export default class SettingCommon extends Component {
|
|
|
320
320
|
const {
|
|
321
321
|
enableGlobalProxy
|
|
322
322
|
} = this.props.config
|
|
323
|
-
const helps = `http# http://proxy-server-over-tcp.com:3128
|
|
324
|
-
https#https://proxy-server-over-tls.com:3129
|
|
325
|
-
socks(v5)#socks://username:password@some-socks-proxy.com:9050 (username & password are optional)
|
|
326
|
-
socks5#socks5://username:password@some-socks-proxy.com:9050 (username & password are optional)
|
|
327
|
-
socks5h#socks5h://username:password@some-socks-proxy.com:9050 (username & password are optional)
|
|
328
|
-
socks4#socks4://some-socks-proxy.com:9050
|
|
329
|
-
socks4a#socks4a://some-socks-proxy.com:9050`
|
|
330
|
-
.split('\n')
|
|
331
|
-
.filter(d => d.trim())
|
|
332
|
-
.map(d => {
|
|
333
|
-
const [protocol, example] = d.split('#')
|
|
334
|
-
return {
|
|
335
|
-
protocol, example
|
|
336
|
-
}
|
|
337
|
-
})
|
|
338
|
-
const cols = Object.keys(helps[0]).map(k => {
|
|
339
|
-
return {
|
|
340
|
-
title: k,
|
|
341
|
-
dataIndex: k,
|
|
342
|
-
key: k,
|
|
343
|
-
render: (k) => k || ''
|
|
344
|
-
}
|
|
345
|
-
})
|
|
346
|
-
const table = (
|
|
347
|
-
<div>
|
|
348
|
-
<Table
|
|
349
|
-
columns={cols}
|
|
350
|
-
dataSource={helps}
|
|
351
|
-
bordered
|
|
352
|
-
pagination={false}
|
|
353
|
-
size='small'
|
|
354
|
-
rowKey='protocol'
|
|
355
|
-
/>
|
|
356
|
-
<div>
|
|
357
|
-
<Link to={proxyHelpLink}>{proxyHelpLink}</Link>
|
|
358
|
-
</div>
|
|
359
|
-
</div>
|
|
360
|
-
)
|
|
361
|
-
const style = {
|
|
362
|
-
height: '414px',
|
|
363
|
-
width: '500px'
|
|
364
|
-
}
|
|
365
323
|
return (
|
|
366
324
|
<div className='pd1b'>
|
|
367
325
|
<div className='pd1b'>
|
|
368
326
|
<span className='pd1r'>
|
|
369
327
|
{e('global')} {e('proxy')}
|
|
370
328
|
<HelpIcon
|
|
371
|
-
|
|
372
|
-
style={{ body: { style } }}
|
|
329
|
+
link={proxyHelpLink}
|
|
373
330
|
/>
|
|
374
331
|
</span>
|
|
375
332
|
<SwitchLabel
|
|
@@ -456,6 +413,7 @@ export default class SettingCommon extends Component {
|
|
|
456
413
|
const {
|
|
457
414
|
langs = []
|
|
458
415
|
} = window.et
|
|
416
|
+
const isWebApp = !!window.et.isWebApp
|
|
459
417
|
const terminalThemes = props.store.getSidebarList(settingMap.terminalThemes)
|
|
460
418
|
const pops = {
|
|
461
419
|
onStartSessions: props.config.onStartSessions,
|
|
@@ -475,9 +433,15 @@ export default class SettingCommon extends Component {
|
|
|
475
433
|
config={props.config}
|
|
476
434
|
store={props.store}
|
|
477
435
|
/>
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
436
|
+
{
|
|
437
|
+
isWebApp
|
|
438
|
+
? null
|
|
439
|
+
: (
|
|
440
|
+
<HotkeySetting
|
|
441
|
+
{...hotkeyProps}
|
|
442
|
+
/>
|
|
443
|
+
)
|
|
444
|
+
}
|
|
481
445
|
<div className='pd1b'>{e('onStartBookmarks')}</div>
|
|
482
446
|
<div className='pd2b'>
|
|
483
447
|
<StartSession
|
|
@@ -502,12 +466,14 @@ export default class SettingCommon extends Component {
|
|
|
502
466
|
}, e('keepaliveIntervalDesc'))
|
|
503
467
|
}
|
|
504
468
|
{
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
469
|
+
isWebApp
|
|
470
|
+
? null
|
|
471
|
+
: this.renderNumber('opacity', {
|
|
472
|
+
step: 0.05,
|
|
473
|
+
min: 0,
|
|
474
|
+
max: 1,
|
|
475
|
+
cls: 'opacity'
|
|
476
|
+
}, e('opacity'))
|
|
511
477
|
}
|
|
512
478
|
|
|
513
479
|
<div className='pd2b'>
|
|
@@ -608,9 +574,12 @@ export default class SettingCommon extends Component {
|
|
|
608
574
|
'allowMultiInstance',
|
|
609
575
|
'disableDeveloperTool',
|
|
610
576
|
'switchTabOnHover',
|
|
577
|
+
'disableTabIndex',
|
|
611
578
|
'disableShortcutBar',
|
|
612
579
|
'debug'
|
|
613
|
-
]
|
|
580
|
+
]
|
|
581
|
+
.filter(name => !isWebApp || !webAppHiddenSettings.includes(name))
|
|
582
|
+
.map(this.renderToggle)
|
|
614
583
|
}
|
|
615
584
|
{
|
|
616
585
|
window.et.isWebApp ? null : <DeepLinkControl />
|
|
@@ -7,6 +7,7 @@ import { pick } from 'lodash-es'
|
|
|
7
7
|
import { Tabs, Spin } from 'antd'
|
|
8
8
|
import { lazy, Suspense } from 'react'
|
|
9
9
|
import SettingModal from './setting-wrap'
|
|
10
|
+
import LazyBoundary from '../common/lazy-boundary'
|
|
10
11
|
import {
|
|
11
12
|
settingMap,
|
|
12
13
|
modals,
|
|
@@ -18,6 +19,7 @@ const TabSettings = lazy(() => import('./tab-settings'))
|
|
|
18
19
|
const TabThemes = lazy(() => import('./tab-themes'))
|
|
19
20
|
const TabProfiles = lazy(() => import('./tab-profiles'))
|
|
20
21
|
const TabWidgets = lazy(() => import('./tab-widgets'))
|
|
22
|
+
const TabTriggers = lazy(() => import('./tab-triggers'))
|
|
21
23
|
|
|
22
24
|
const Loading = () => <div style={{ padding: 20, textAlign: 'center' }}><Spin /></div>
|
|
23
25
|
|
|
@@ -107,6 +109,11 @@ export default auto(function SettingModalWrap (props) {
|
|
|
107
109
|
label: e(settingMap.quickCommands),
|
|
108
110
|
children: null
|
|
109
111
|
},
|
|
112
|
+
{
|
|
113
|
+
key: settingMap.triggers,
|
|
114
|
+
label: <span>{e('triggers')} <sup>Beta</sup></span>,
|
|
115
|
+
children: null
|
|
116
|
+
},
|
|
110
117
|
{
|
|
111
118
|
key: settingMap.profiles,
|
|
112
119
|
label: e(settingMap.profiles),
|
|
@@ -132,48 +139,56 @@ export default auto(function SettingModalWrap (props) {
|
|
|
132
139
|
<Tabs
|
|
133
140
|
{...tabsProps}
|
|
134
141
|
/>
|
|
135
|
-
<
|
|
136
|
-
<
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
142
|
+
<LazyBoundary>
|
|
143
|
+
<Suspense fallback={<Loading />}>
|
|
144
|
+
<TabQuickCommands
|
|
145
|
+
listProps={props0}
|
|
146
|
+
settingItem={settingItem}
|
|
147
|
+
formProps={formProps}
|
|
148
|
+
store={store}
|
|
149
|
+
settingTab={settingTab}
|
|
150
|
+
/>
|
|
151
|
+
<TabTriggers
|
|
152
|
+
listProps={props0}
|
|
153
|
+
settingItem={settingItem}
|
|
154
|
+
store={store}
|
|
155
|
+
settingTab={settingTab}
|
|
156
|
+
/>
|
|
157
|
+
<TabBookmarks
|
|
158
|
+
treeProps={treeProps}
|
|
159
|
+
settingItem={settingItem}
|
|
160
|
+
formProps={formProps}
|
|
161
|
+
settingTab={settingTab}
|
|
162
|
+
/>
|
|
163
|
+
<TabSettings
|
|
164
|
+
listProps={props0}
|
|
165
|
+
settingItem={settingItem}
|
|
166
|
+
settingTab={settingTab}
|
|
167
|
+
store={store}
|
|
168
|
+
/>
|
|
169
|
+
<TabThemes
|
|
170
|
+
listProps={props0}
|
|
171
|
+
settingItem={settingItem}
|
|
172
|
+
formProps={formProps}
|
|
173
|
+
store={store}
|
|
174
|
+
settingTab={settingTab}
|
|
175
|
+
/>
|
|
176
|
+
<TabProfiles
|
|
177
|
+
listProps={props0}
|
|
178
|
+
settingItem={settingItem}
|
|
179
|
+
formProps={formProps}
|
|
180
|
+
store={store}
|
|
181
|
+
settingTab={settingTab}
|
|
182
|
+
/>
|
|
183
|
+
<TabWidgets
|
|
184
|
+
listProps={props0}
|
|
185
|
+
settingItem={settingItem}
|
|
186
|
+
formProps={formProps}
|
|
187
|
+
store={store}
|
|
188
|
+
settingTab={settingTab}
|
|
189
|
+
/>
|
|
190
|
+
</Suspense>
|
|
191
|
+
</LazyBoundary>
|
|
177
192
|
</>
|
|
178
193
|
)
|
|
179
194
|
}
|
|
@@ -509,7 +509,7 @@ export default class SettingTerminal extends Component {
|
|
|
509
509
|
{
|
|
510
510
|
this.renderNumber('fontSize', {
|
|
511
511
|
step: 1,
|
|
512
|
-
min:
|
|
512
|
+
min: 5
|
|
513
513
|
}, `${e('default')} ${e('fontSize')}`, 400)
|
|
514
514
|
}
|
|
515
515
|
<div className='pd2b'>
|
|
@@ -575,9 +575,14 @@ export default class SettingTerminal extends Component {
|
|
|
575
575
|
'sftpPathFollowSsh',
|
|
576
576
|
'sshSftpSplitView',
|
|
577
577
|
'showCmdSuggestions',
|
|
578
|
-
'autoReconnectTerminal'
|
|
578
|
+
'autoReconnectTerminal',
|
|
579
|
+
'restoreTerminalSessionOnReload'
|
|
579
580
|
].map(d => this.renderToggle(d))
|
|
580
581
|
}
|
|
582
|
+
{
|
|
583
|
+
// label differs from the config key
|
|
584
|
+
this.renderToggle('remoteMonitorBarEnabled', 'pd2b', e('monitorBar'))
|
|
585
|
+
}
|
|
581
586
|
<div className='pd1b'>{e('dragDropBehavior')}</div>
|
|
582
587
|
<Select
|
|
583
588
|
onChange={this.handleChangeDragDropBehavior}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Button, Form } from 'antd'
|
|
2
|
+
import SettingCol from './col'
|
|
3
|
+
import TriggerSettingList from '../triggers/trigger-setting-list'
|
|
4
|
+
import TriggerForm, { buildTriggerFromFormValues } from '../triggers/trigger-form'
|
|
5
|
+
import { validateTriggers } from '../terminal/automation/trigger-engine'
|
|
6
|
+
import message from '../common/message'
|
|
7
|
+
import { settingMap } from '../../common/constants'
|
|
8
|
+
|
|
9
|
+
const e = window.translate
|
|
10
|
+
|
|
11
|
+
export default function TabTriggers (props) {
|
|
12
|
+
const [form] = Form.useForm()
|
|
13
|
+
const {
|
|
14
|
+
settingTab,
|
|
15
|
+
store,
|
|
16
|
+
settingItem,
|
|
17
|
+
listProps
|
|
18
|
+
} = props
|
|
19
|
+
if (settingTab !== settingMap.triggers) {
|
|
20
|
+
return null
|
|
21
|
+
}
|
|
22
|
+
const handleSave = async () => {
|
|
23
|
+
try {
|
|
24
|
+
const v = await form.validateFields()
|
|
25
|
+
const next = buildTriggerFromFormValues(settingItem, v)
|
|
26
|
+
const errors = validateTriggers([next])
|
|
27
|
+
if (errors.length) {
|
|
28
|
+
message.error(errors[0])
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
if (settingItem.id) {
|
|
32
|
+
store.editTrigger(settingItem.id, next)
|
|
33
|
+
} else {
|
|
34
|
+
store.addTrigger(next)
|
|
35
|
+
store.setSettingItem({
|
|
36
|
+
id: '',
|
|
37
|
+
name: settingMap.triggers
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
message.success(e('saved'))
|
|
41
|
+
} catch (err) {
|
|
42
|
+
// validation failed, keep form as is
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<div
|
|
48
|
+
className='setting-tabs-triggers'
|
|
49
|
+
>
|
|
50
|
+
<SettingCol>
|
|
51
|
+
<TriggerSettingList
|
|
52
|
+
{...listProps}
|
|
53
|
+
/>
|
|
54
|
+
<div key={settingItem.id}>
|
|
55
|
+
<TriggerForm
|
|
56
|
+
form={form}
|
|
57
|
+
initial={settingItem}
|
|
58
|
+
/>
|
|
59
|
+
<div className='pd2l'>
|
|
60
|
+
<Button
|
|
61
|
+
type='primary'
|
|
62
|
+
onClick={handleSave}
|
|
63
|
+
>
|
|
64
|
+
{e('save')}
|
|
65
|
+
</Button>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</SettingCol>
|
|
69
|
+
</div>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
@@ -12,6 +12,7 @@ import { mode2permission, permission2mode } from '../../common/mode2permission'
|
|
|
12
12
|
import FileIcon from './file-icon'
|
|
13
13
|
import { filesize } from 'filesize'
|
|
14
14
|
import { refsStatic } from '../common/ref'
|
|
15
|
+
import LazyBoundary from '../common/lazy-boundary'
|
|
15
16
|
import './file-compare-modal.styl'
|
|
16
17
|
|
|
17
18
|
const e = window.translate
|
|
@@ -169,9 +170,11 @@ export default class FileCompareModal extends React.PureComponent {
|
|
|
169
170
|
key: 'code',
|
|
170
171
|
label: e('code'),
|
|
171
172
|
children: (
|
|
172
|
-
<
|
|
173
|
-
<
|
|
174
|
-
|
|
173
|
+
<LazyBoundary>
|
|
174
|
+
<Suspense fallback={<Loading />}>
|
|
175
|
+
<CodeCompare file1={file1} file2={file2} tab={tab} />
|
|
176
|
+
</Suspense>
|
|
177
|
+
</LazyBoundary>
|
|
175
178
|
)
|
|
176
179
|
}
|
|
177
180
|
]
|
|
@@ -36,6 +36,7 @@ import { filesize } from 'filesize'
|
|
|
36
36
|
import { createTransferProps } from './transfer-common'
|
|
37
37
|
import generate from '../../common/uid'
|
|
38
38
|
import sanitizeFilename from '../../common/sanitize-filename'
|
|
39
|
+
import { openTextEditor } from '../text-editor/open-text-editor'
|
|
39
40
|
import { refsStatic, refs, filesRef } from '../common/ref'
|
|
40
41
|
import iconsMap from '../sys-menu/icons-map'
|
|
41
42
|
import message from '../common/message'
|
|
@@ -702,7 +703,7 @@ export default class FileSection extends React.Component {
|
|
|
702
703
|
}
|
|
703
704
|
|
|
704
705
|
onFileChange = (e, text) => {
|
|
705
|
-
this.editor
|
|
706
|
+
this.editor?.editWithSystemEditorDone({
|
|
706
707
|
id: this.id,
|
|
707
708
|
text
|
|
708
709
|
})
|
|
@@ -773,7 +774,8 @@ export default class FileSection extends React.Component {
|
|
|
773
774
|
|
|
774
775
|
editFile = () => {
|
|
775
776
|
refs.add(this.id, this)
|
|
776
|
-
this
|
|
777
|
+
// editor is lazy loaded, this will mount it on demand
|
|
778
|
+
openTextEditor({
|
|
777
779
|
id: this.id,
|
|
778
780
|
file: this.state.file
|
|
779
781
|
})
|
|
@@ -1261,7 +1263,7 @@ export default class FileSection extends React.Component {
|
|
|
1261
1263
|
if (isDirectory && id === 'size') {
|
|
1262
1264
|
value = null
|
|
1263
1265
|
} else if (!isDirectory && id === 'size') {
|
|
1264
|
-
value = filesize(value)
|
|
1266
|
+
value = filesize(Number(value) || 0)
|
|
1265
1267
|
} else if (id === 'owner') {
|
|
1266
1268
|
const { type } = this.props
|
|
1267
1269
|
value = this.props[`${type}UidTree`]['' + value] || value
|
|
@@ -26,6 +26,15 @@ function parseNames (str) {
|
|
|
26
26
|
const linuxListUser = 'cat /etc/passwd'
|
|
27
27
|
const linuxListGroup = 'cat /etc/group'
|
|
28
28
|
|
|
29
|
+
// The local shell (node-bash) only exists on desktop builds; web/mobile builds
|
|
30
|
+
// (electerm-web in a browser, electerm-ios/electerm-android) ship without it, so
|
|
31
|
+
// `fs.run` rejects. These owner/group lists are a best-effort nicety for the
|
|
32
|
+
// local file panel, and every rejection would surface as a spurious error
|
|
33
|
+
// notification on those platforms — skip the probe entirely when we know there
|
|
34
|
+
// is no local shell. `hasNodePty === false` is the explicit signal reported by
|
|
35
|
+
// the server (see checkNodePty); an absent flag keeps desktop behaviour intact.
|
|
36
|
+
const noLocalShell = isWin || window.et.hasNodePty === false
|
|
37
|
+
|
|
29
38
|
export async function remoteListUsers (pid) {
|
|
30
39
|
const users = await runCmd(pid, linuxListUser)
|
|
31
40
|
.catch(console.error)
|
|
@@ -45,7 +54,7 @@ export async function remoteListGroups (pid) {
|
|
|
45
54
|
}
|
|
46
55
|
|
|
47
56
|
export async function localListUsers () {
|
|
48
|
-
if (
|
|
57
|
+
if (noLocalShell) {
|
|
49
58
|
return {}
|
|
50
59
|
} else if (isMac) {
|
|
51
60
|
const g = await window.fs.run('dscl . -list /Users UniqueID')
|
|
@@ -72,7 +81,7 @@ export async function localListUsers () {
|
|
|
72
81
|
}
|
|
73
82
|
|
|
74
83
|
export async function localListGroups () {
|
|
75
|
-
if (
|
|
84
|
+
if (noLocalShell) {
|
|
76
85
|
return {}
|
|
77
86
|
} else if (isMac) {
|
|
78
87
|
const g = await window.fs.run('dscl . list /Groups PrimaryGroupID')
|
|
@@ -4,7 +4,7 @@ import './right-side-panel.styl'
|
|
|
4
4
|
import {
|
|
5
5
|
CloseCircleOutlined,
|
|
6
6
|
PushpinOutlined,
|
|
7
|
-
|
|
7
|
+
BarChartOutlined
|
|
8
8
|
} from '@ant-design/icons'
|
|
9
9
|
import {
|
|
10
10
|
Typography,
|
|
@@ -29,7 +29,7 @@ export default memo(function RightSidePanel (
|
|
|
29
29
|
}
|
|
30
30
|
const tag = rightPanelTab === 'ai'
|
|
31
31
|
? <Tag className='mg1r'>AI</Tag>
|
|
32
|
-
: <
|
|
32
|
+
: <BarChartOutlined className='mg1r' />
|
|
33
33
|
|
|
34
34
|
function onDragEnd (nw) {
|
|
35
35
|
window.store.setRightSidePanelWidth(nw)
|
|
@@ -65,6 +65,7 @@ class MenuBtn extends PureComponent {
|
|
|
65
65
|
renderContext = () => {
|
|
66
66
|
const items = [
|
|
67
67
|
{
|
|
68
|
+
key: 'onNewSsh',
|
|
68
69
|
func: 'onNewSsh',
|
|
69
70
|
icon: 'CodeFilled',
|
|
70
71
|
text: e('newBookmark'),
|
|
@@ -73,6 +74,7 @@ class MenuBtn extends PureComponent {
|
|
|
73
74
|
]
|
|
74
75
|
if (window.store.hasNodePty) {
|
|
75
76
|
items.push({
|
|
77
|
+
key: 'addTab',
|
|
76
78
|
func: 'addTab',
|
|
77
79
|
icon: 'RightSquareFilled',
|
|
78
80
|
text: e('newTab'),
|
|
@@ -83,6 +85,7 @@ class MenuBtn extends PureComponent {
|
|
|
83
85
|
// type: 'hr'
|
|
84
86
|
// },
|
|
85
87
|
items.push({
|
|
88
|
+
key: 'bookmarks',
|
|
86
89
|
noCloseMenu: true,
|
|
87
90
|
icon: 'BookOutlined',
|
|
88
91
|
text: e('bookmarks'),
|
|
@@ -90,18 +93,21 @@ class MenuBtn extends PureComponent {
|
|
|
90
93
|
})
|
|
91
94
|
items.push(
|
|
92
95
|
{
|
|
96
|
+
key: 'history',
|
|
93
97
|
noCloseMenu: true,
|
|
94
98
|
icon: 'ClockCircleOutlined',
|
|
95
99
|
text: e('history'),
|
|
96
100
|
submenu: 'History'
|
|
97
101
|
},
|
|
98
102
|
{
|
|
103
|
+
key: 'sessions',
|
|
99
104
|
noCloseMenu: true,
|
|
100
105
|
icon: 'BarsOutlined',
|
|
101
106
|
text: e('sessions'),
|
|
102
107
|
submenu: 'Tabs'
|
|
103
108
|
},
|
|
104
109
|
{
|
|
110
|
+
key: 'layout',
|
|
105
111
|
icon: 'AppstoreOutlined',
|
|
106
112
|
text: e('layout'),
|
|
107
113
|
submenu: 'Layout'
|
|
@@ -110,16 +116,19 @@ class MenuBtn extends PureComponent {
|
|
|
110
116
|
// type: 'hr'
|
|
111
117
|
// },
|
|
112
118
|
{
|
|
119
|
+
key: 'openAbout',
|
|
113
120
|
func: 'openAbout',
|
|
114
121
|
icon: 'InfoCircleOutlined',
|
|
115
122
|
text: e('about')
|
|
116
123
|
},
|
|
117
124
|
{
|
|
125
|
+
key: 'openSetting',
|
|
118
126
|
func: 'openSetting',
|
|
119
127
|
icon: 'SettingOutlined',
|
|
120
128
|
text: e('settings')
|
|
121
129
|
},
|
|
122
130
|
{
|
|
131
|
+
key: 'openDevTools',
|
|
123
132
|
func: 'openDevTools',
|
|
124
133
|
icon: 'LeftSquareFilled',
|
|
125
134
|
text: e('toggledevtools')
|
|
@@ -128,19 +137,23 @@ class MenuBtn extends PureComponent {
|
|
|
128
137
|
// type: 'hr'
|
|
129
138
|
// },
|
|
130
139
|
{
|
|
140
|
+
key: 'zoom',
|
|
131
141
|
module: 'Zoom'
|
|
132
142
|
},
|
|
133
143
|
{
|
|
144
|
+
key: 'minimize',
|
|
134
145
|
func: 'minimize',
|
|
135
146
|
icon: 'SwitcherFilled',
|
|
136
147
|
text: e('minimize')
|
|
137
148
|
},
|
|
138
149
|
{
|
|
150
|
+
key: 'maximize',
|
|
139
151
|
func: 'maximize',
|
|
140
152
|
icon: 'LayoutFilled',
|
|
141
153
|
text: e('maximize')
|
|
142
154
|
},
|
|
143
155
|
{
|
|
156
|
+
key: 'reload',
|
|
144
157
|
func: 'reload',
|
|
145
158
|
icon: 'ReloadOutlined',
|
|
146
159
|
text: e('reload')
|
|
@@ -149,6 +162,7 @@ class MenuBtn extends PureComponent {
|
|
|
149
162
|
// type: 'hr'
|
|
150
163
|
// },
|
|
151
164
|
{
|
|
165
|
+
key: 'onCheckUpdate',
|
|
152
166
|
func: 'onCheckUpdate',
|
|
153
167
|
icon: 'UpCircleOutlined',
|
|
154
168
|
text: e('checkForUpdate')
|
|
@@ -157,17 +171,32 @@ class MenuBtn extends PureComponent {
|
|
|
157
171
|
// type: 'hr'
|
|
158
172
|
// },
|
|
159
173
|
{
|
|
174
|
+
key: 'restart',
|
|
160
175
|
func: 'restart',
|
|
161
176
|
icon: 'RedoOutlined',
|
|
162
177
|
text: e('restart')
|
|
163
178
|
},
|
|
164
179
|
{
|
|
180
|
+
key: 'close',
|
|
165
181
|
func: 'close',
|
|
166
182
|
icon: 'CloseOutlined',
|
|
167
183
|
text: e('close')
|
|
168
184
|
}
|
|
169
185
|
)
|
|
170
|
-
return items
|
|
186
|
+
return this.filterMenus(items)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Only show menus listed in window.et.sysMenus, when it is defined,
|
|
190
|
+
// eg: window.et.sysMenus = ['onNewSsh', 'bookmarks', 'openSetting', 'close']
|
|
191
|
+
// available keys: onNewSsh, addTab, bookmarks, history, sessions, layout,
|
|
192
|
+
// openAbout, openSetting, openDevTools, zoom, minimize, maximize, reload,
|
|
193
|
+
// onCheckUpdate, restart, close
|
|
194
|
+
filterMenus = (items) => {
|
|
195
|
+
const { sysMenus } = window.et || {}
|
|
196
|
+
if (!Array.isArray(sysMenus)) {
|
|
197
|
+
return items
|
|
198
|
+
}
|
|
199
|
+
return items.filter(d => d.type === 'hr' || sysMenus.includes(d.key))
|
|
171
200
|
}
|
|
172
201
|
|
|
173
202
|
renderMenu () {
|
|
@@ -225,7 +225,7 @@ export default class Tabs extends Component {
|
|
|
225
225
|
return {
|
|
226
226
|
key: i + '##' + t.id,
|
|
227
227
|
label: (
|
|
228
|
-
<span><TabTitle tab={t} /></span>
|
|
228
|
+
<span><TabTitle tab={t} config={this.props.config} /></span>
|
|
229
229
|
),
|
|
230
230
|
onClick: () => this.handleClickMenu({ key: i + '##' + t.id })
|
|
231
231
|
}
|
|
@@ -423,7 +423,7 @@ export default class Tabs extends Component {
|
|
|
423
423
|
return {
|
|
424
424
|
key: i + '##' + t.id,
|
|
425
425
|
label: (
|
|
426
|
-
<span><TabTitle tab={t} /></span>
|
|
426
|
+
<span><TabTitle tab={t} config={this.props.config} /></span>
|
|
427
427
|
),
|
|
428
428
|
onClick: () => this.handleClickMenu({ key: i + '##' + t.id })
|
|
429
429
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import createName from '../../common/create-title'
|
|
2
2
|
|
|
3
3
|
export default function tabTitle (props) {
|
|
4
|
-
const { tab } = props
|
|
4
|
+
const { tab, config } = props
|
|
5
5
|
const title = createName(tab)
|
|
6
6
|
const { tabCount, color } = props.tab
|
|
7
7
|
const styleTag = color
|
|
@@ -9,7 +9,8 @@ export default function tabTitle (props) {
|
|
|
9
9
|
: {}
|
|
10
10
|
return (
|
|
11
11
|
<span className='tab-title'>
|
|
12
|
-
<span style={styleTag}>●</span>
|
|
12
|
+
<span style={styleTag}>●</span>
|
|
13
|
+
{!(config && config.disableTabIndex) ? ` ${tabCount}.` : ''} {title}
|
|
13
14
|
</span>
|
|
14
15
|
)
|
|
15
16
|
}
|
|
@@ -561,7 +561,11 @@ class Tab extends Component {
|
|
|
561
561
|
)
|
|
562
562
|
}
|
|
563
563
|
<span className='tab-title'>
|
|
564
|
-
|
|
564
|
+
{!(config && config.disableTabIndex)
|
|
565
|
+
? (
|
|
566
|
+
<span className='iblock mg1r tab-count' style={styleTag}>{tabCount}</span>
|
|
567
|
+
)
|
|
568
|
+
: null}
|
|
565
569
|
{tab.isPinned && <PushpinFilled className='tab-pin' />}
|
|
566
570
|
<span className='mg1r'>{title}</span>
|
|
567
571
|
</span>
|