@electerm/electerm-react 5.3.15 → 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 +23 -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/bookmark-form/index.jsx +10 -8
- 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 +80 -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/col.jsx +32 -6
- package/client/components/setting-panel/list.styl +12 -0
- package/client/components/setting-panel/setting-common.jsx +25 -56
- package/client/components/setting-panel/setting-mobile-breadcrumb.jsx +29 -0
- package/client/components/setting-panel/setting-modal.jsx +64 -44
- package/client/components/setting-panel/setting-terminal.jsx +7 -2
- package/client/components/setting-panel/setting-wrap.jsx +0 -3
- package/client/components/setting-panel/setting-wrap.styl +80 -11
- 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/sidebar/index.jsx +28 -21
- package/client/components/sidebar/left-sidebar-icons.jsx +1 -1
- package/client/components/sidebar/sidebar.styl +16 -0
- 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/tabs/tabs.styl +4 -0
- 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 +32 -27
- 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/theme/theme-form.jsx +22 -0
- package/client/components/tree-list/bookmark-transport.jsx +7 -31
- package/client/components/tree-list/tree-list.styl +13 -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 +14 -0
- package/client/store/mcp-handler.js +158 -30
- package/client/store/setting.js +20 -0
- package/client/store/sidebar.js +12 -0
- package/client/store/store.js +2 -0
- package/client/store/sync.js +45 -9
- package/client/store/system-menu.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 />
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* breadcrumb shown at the top of the settings content view on mobile.
|
|
3
|
+
* - parent crumb = the active setting tab, clickable, returns to the menu list
|
|
4
|
+
* - current crumb = the selected item name, plain text
|
|
5
|
+
* `onBack` + labels are props so it stays reusable for other panels
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { ArrowLeftOutlined } from '@ant-design/icons'
|
|
9
|
+
|
|
10
|
+
export default function SettingMobileBreadcrumb (props) {
|
|
11
|
+
const {
|
|
12
|
+
onBack,
|
|
13
|
+
parentLabel,
|
|
14
|
+
currentLabel
|
|
15
|
+
} = props
|
|
16
|
+
return (
|
|
17
|
+
<div className='setting-mobile-back'>
|
|
18
|
+
<button
|
|
19
|
+
className='setting-mobile-back-btn'
|
|
20
|
+
onClick={onBack}
|
|
21
|
+
>
|
|
22
|
+
<ArrowLeftOutlined />
|
|
23
|
+
<span className='setting-mobile-back-parent'>{parentLabel}</span>
|
|
24
|
+
</button>
|
|
25
|
+
<span className='setting-mobile-back-sep'>></span>
|
|
26
|
+
<span className='setting-mobile-back-current elli'>{currentLabel}</span>
|
|
27
|
+
</div>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
@@ -7,9 +7,11 @@ 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
|
-
modals
|
|
13
|
+
modals,
|
|
14
|
+
settingPanelMobileBreakpoint
|
|
13
15
|
} from '../../common/constants'
|
|
14
16
|
const TabBookmarks = lazy(() => import('./tab-bookmarks'))
|
|
15
17
|
const TabQuickCommands = lazy(() => import('./tab-quick-commands'))
|
|
@@ -17,6 +19,7 @@ const TabSettings = lazy(() => import('./tab-settings'))
|
|
|
17
19
|
const TabThemes = lazy(() => import('./tab-themes'))
|
|
18
20
|
const TabProfiles = lazy(() => import('./tab-profiles'))
|
|
19
21
|
const TabWidgets = lazy(() => import('./tab-widgets'))
|
|
22
|
+
const TabTriggers = lazy(() => import('./tab-triggers'))
|
|
20
23
|
|
|
21
24
|
const Loading = () => <div style={{ padding: 20, textAlign: 'center' }}><Spin /></div>
|
|
22
25
|
|
|
@@ -25,6 +28,11 @@ const e = window.translate
|
|
|
25
28
|
export default auto(function SettingModalWrap (props) {
|
|
26
29
|
const selectItem = (item) => {
|
|
27
30
|
window.store.setSettingItem(item)
|
|
31
|
+
// narrow panels drill into the right col content after picking a menu
|
|
32
|
+
// item — same 800px breakpoint as the setting panel media query
|
|
33
|
+
if (window.store.innerWidth <= settingPanelMobileBreakpoint) {
|
|
34
|
+
window.store.settingMobileView = 'content'
|
|
35
|
+
}
|
|
28
36
|
}
|
|
29
37
|
|
|
30
38
|
function renderTabs () {
|
|
@@ -101,6 +109,11 @@ export default auto(function SettingModalWrap (props) {
|
|
|
101
109
|
label: e(settingMap.quickCommands),
|
|
102
110
|
children: null
|
|
103
111
|
},
|
|
112
|
+
{
|
|
113
|
+
key: settingMap.triggers,
|
|
114
|
+
label: <span>{e('triggers')} <sup>Beta</sup></span>,
|
|
115
|
+
children: null
|
|
116
|
+
},
|
|
104
117
|
{
|
|
105
118
|
key: settingMap.profiles,
|
|
106
119
|
label: e(settingMap.profiles),
|
|
@@ -126,48 +139,56 @@ export default auto(function SettingModalWrap (props) {
|
|
|
126
139
|
<Tabs
|
|
127
140
|
{...tabsProps}
|
|
128
141
|
/>
|
|
129
|
-
<
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
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>
|
|
171
192
|
</>
|
|
172
193
|
)
|
|
173
194
|
}
|
|
@@ -188,7 +209,6 @@ export default auto(function SettingModalWrap (props) {
|
|
|
188
209
|
visible={show}
|
|
189
210
|
useSystemTitleBar={useSystemTitleBar}
|
|
190
211
|
innerWidth={innerWidth}
|
|
191
|
-
isMobile={props.store.isMobile}
|
|
192
212
|
>
|
|
193
213
|
{renderTabs()}
|
|
194
214
|
</SettingModal>
|
|
@@ -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}
|
|
@@ -67,34 +67,103 @@
|
|
|
67
67
|
.setting-col
|
|
68
68
|
::-webkit-scrollbar
|
|
69
69
|
width 0
|
|
70
|
-
@media (max-width:
|
|
70
|
+
@media (max-width: 800px)
|
|
71
71
|
.setting-col
|
|
72
72
|
position fixed
|
|
73
73
|
top 128px
|
|
74
74
|
bottom 0
|
|
75
75
|
left var(--left-side-bar-width, 43px)
|
|
76
76
|
right 0
|
|
77
|
-
|
|
77
|
+
display flex
|
|
78
|
+
flex-direction column
|
|
79
|
+
overflow hidden
|
|
78
80
|
.setting-row
|
|
79
81
|
position static
|
|
80
82
|
top auto
|
|
83
|
+
// right close button is redundant with the left one on mobile
|
|
84
|
+
.close-setting-wrap:not(.alt-close-setting-wrap)
|
|
85
|
+
display none
|
|
86
|
+
// menu view by default: the left col list fills the panel
|
|
81
87
|
.setting-row-left
|
|
88
|
+
flex 1
|
|
89
|
+
min-height 0
|
|
90
|
+
overflow-y auto
|
|
91
|
+
position static
|
|
92
|
+
top auto
|
|
93
|
+
bottom auto
|
|
82
94
|
left auto
|
|
83
95
|
width auto
|
|
84
|
-
|
|
85
|
-
padding 138px 10px 10px 10px
|
|
96
|
+
padding 10px
|
|
86
97
|
.setting-row-right
|
|
87
|
-
|
|
98
|
+
display none
|
|
99
|
+
position static
|
|
100
|
+
top auto
|
|
88
101
|
right auto
|
|
89
102
|
bottom auto
|
|
90
|
-
|
|
103
|
+
left auto
|
|
104
|
+
width auto
|
|
91
105
|
padding 10px
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
106
|
+
// content view: fixed breadcrumb on top, right col content scrolls below
|
|
107
|
+
.setting-view-content
|
|
108
|
+
.setting-mobile-back
|
|
109
|
+
display flex
|
|
110
|
+
.setting-row-left
|
|
111
|
+
display none
|
|
112
|
+
.setting-row-right
|
|
113
|
+
display flex
|
|
114
|
+
flex-direction column
|
|
115
|
+
flex 1
|
|
116
|
+
min-height 0
|
|
117
|
+
overflow hidden
|
|
118
|
+
position static
|
|
119
|
+
top auto
|
|
120
|
+
right auto
|
|
121
|
+
bottom auto
|
|
122
|
+
left auto
|
|
123
|
+
width auto
|
|
124
|
+
padding 10px
|
|
125
|
+
.setting-col-content
|
|
126
|
+
flex 1
|
|
127
|
+
overflow-y auto
|
|
128
|
+
min-height 0
|
|
96
129
|
.setting-tabs-bookmarks
|
|
97
130
|
.setting-row-left
|
|
98
131
|
width auto
|
|
99
132
|
.setting-row-right
|
|
100
|
-
left auto
|
|
133
|
+
left auto
|
|
134
|
+
|
|
135
|
+
// breadcrumb used on the narrow (mobile) content view; hidden by default and
|
|
136
|
+
// re-shown by `.setting-view-content` inside the 800px media query above
|
|
137
|
+
.setting-mobile-back
|
|
138
|
+
display none
|
|
139
|
+
flex-shrink 0
|
|
140
|
+
align-items center
|
|
141
|
+
gap 4px
|
|
142
|
+
padding 8px 10px
|
|
143
|
+
background var(--main)
|
|
144
|
+
border-bottom 1px solid var(--main-light)
|
|
145
|
+
z-index 10
|
|
146
|
+
.setting-mobile-back-btn
|
|
147
|
+
display flex
|
|
148
|
+
align-items center
|
|
149
|
+
gap 4px
|
|
150
|
+
height 24px
|
|
151
|
+
padding 0 6px
|
|
152
|
+
font-size 13px
|
|
153
|
+
color var(--primary)
|
|
154
|
+
background transparent
|
|
155
|
+
border 0
|
|
156
|
+
border-radius 4px
|
|
157
|
+
cursor pointer
|
|
158
|
+
&:hover
|
|
159
|
+
background var(--primary)
|
|
160
|
+
color var(--primary-contrast)
|
|
161
|
+
.setting-mobile-back-sep
|
|
162
|
+
color var(--text-dark)
|
|
163
|
+
font-size 13px
|
|
164
|
+
line-height 24px
|
|
165
|
+
padding 0 2px
|
|
166
|
+
.setting-mobile-back-current
|
|
167
|
+
font-size 13px
|
|
168
|
+
min-width 0
|
|
169
|
+
max-width 60%
|
|
@@ -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)
|