@electerm/electerm-react 1.72.48 → 1.80.2
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/client/common/constants.js +1 -1
- package/client/common/sftp.js +3 -1
- package/client/components/ai/ai-config.jsx +7 -1
- package/client/components/batch-op/batch-op.jsx +4 -5
- package/client/components/bg/css-overwrite.jsx +179 -0
- package/client/components/bg/shapes.js +501 -0
- package/client/components/bookmark-form/form-tabs.jsx +1 -0
- package/client/components/bookmark-form/local-form-ui.jsx +7 -1
- package/client/components/bookmark-form/render-bg.jsx +43 -0
- package/client/components/bookmark-form/serial-form-ui.jsx +7 -1
- package/client/components/bookmark-form/ssh-form-ui.jsx +14 -3
- package/client/components/bookmark-form/telnet-form-ui.jsx +7 -1
- package/client/components/bookmark-form/use-ui.jsx +68 -72
- package/client/components/common/ref.js +2 -0
- package/client/components/{sftp/confirm-modal-store.jsx → file-transfer/conflict-resolve.jsx} +86 -48
- package/client/components/file-transfer/transfer-queue.jsx +151 -0
- package/client/components/file-transfer/transfer.jsx +582 -0
- package/client/components/{sftp → file-transfer}/transports-action-store.jsx +35 -32
- package/client/components/{sftp → file-transfer}/transports-ui-store.jsx +2 -2
- package/client/components/main/main.jsx +25 -18
- package/client/components/main/wrapper.styl +16 -0
- package/client/components/profile/profile-list.jsx +1 -1
- package/client/components/quick-commands/qm.styl +4 -1
- package/client/components/quick-commands/quick-commands-list.jsx +16 -4
- package/client/components/setting-panel/list.jsx +1 -1
- package/client/components/setting-panel/setting-terminal.jsx +2 -1
- package/client/components/setting-panel/terminal-bg-config.jsx +15 -2
- package/client/components/sftp/file-info-modal.jsx +3 -0
- package/client/components/sftp/file-item.jsx +25 -23
- package/client/components/sftp/file-read.js +1 -27
- package/client/components/sftp/list-table-ui.jsx +2 -2
- package/client/components/sidebar/transfer-history-modal.jsx +1 -1
- package/client/components/sidebar/transfer-list-control.jsx +1 -1
- package/client/components/sidebar/transport-ui.jsx +16 -9
- package/client/components/terminal/terminal.jsx +23 -1
- package/client/components/text-editor/simple-editor.jsx +164 -0
- package/client/components/text-editor/text-editor-form.jsx +6 -9
- package/client/css/includes/box.styl +2 -2
- package/client/store/tab.js +5 -1
- package/client/store/transfer-list.js +10 -51
- package/package.json +1 -1
- package/client/components/main/css-overwrite.jsx +0 -91
- package/client/components/sftp/transfer-conflict-store.jsx +0 -284
- package/client/components/sftp/transport-action-store.jsx +0 -422
- package/client/components/sftp/zip.js +0 -42
- /package/client/components/{main → bg}/custom-css.jsx +0 -0
- /package/client/components/{sftp → file-transfer}/transfer-speed-format.js +0 -0
- /package/client/components/{sftp → file-transfer}/transfer.styl +0 -0
|
@@ -38,7 +38,7 @@ export const contextMenuPaddingTop = 10
|
|
|
38
38
|
export const sftpControlHeight = 42 + 30
|
|
39
39
|
export const sidebarWidth = 43
|
|
40
40
|
export const maxHistory = 50
|
|
41
|
-
export const maxTransport =
|
|
41
|
+
export const maxTransport = 5
|
|
42
42
|
export const maxSftpHistory = 20
|
|
43
43
|
export const maxZoom = 8
|
|
44
44
|
export const minZoom = 0.5
|
package/client/common/sftp.js
CHANGED
|
@@ -33,12 +33,14 @@ class Sftp {
|
|
|
33
33
|
type: func
|
|
34
34
|
})
|
|
35
35
|
}
|
|
36
|
-
const
|
|
36
|
+
const fid = generate()
|
|
37
|
+
const uid = func + ':' + fid
|
|
37
38
|
// let ws = await initWs()
|
|
38
39
|
return new Promise((resolve, reject) => {
|
|
39
40
|
ws.s({
|
|
40
41
|
action: 'sftp-func',
|
|
41
42
|
id,
|
|
43
|
+
uid,
|
|
42
44
|
func,
|
|
43
45
|
args,
|
|
44
46
|
sessionId
|
|
@@ -82,6 +82,9 @@ export default function AIConfigForm ({ initialValues, onSubmit, showAIConfig })
|
|
|
82
82
|
type='info'
|
|
83
83
|
className='mg2y'
|
|
84
84
|
/>
|
|
85
|
+
<p>
|
|
86
|
+
Full Url: {initialValues?.baseURLAI}{initialValues?.apiPathAI}
|
|
87
|
+
</p>
|
|
85
88
|
<Form
|
|
86
89
|
form={form}
|
|
87
90
|
onFinish={handleSubmit}
|
|
@@ -112,10 +115,13 @@ export default function AIConfigForm ({ initialValues, onSubmit, showAIConfig })
|
|
|
112
115
|
<Form.Item
|
|
113
116
|
label='API PATH'
|
|
114
117
|
name='apiPathAI'
|
|
118
|
+
rules={[
|
|
119
|
+
{ required: true, message: 'Please input API PATH' }
|
|
120
|
+
]}
|
|
115
121
|
noStyle
|
|
116
122
|
>
|
|
117
123
|
<Input
|
|
118
|
-
placeholder='
|
|
124
|
+
placeholder='/chat/completions'
|
|
119
125
|
style={{ width: '25%' }}
|
|
120
126
|
/>
|
|
121
127
|
</Form.Item>
|
|
@@ -18,7 +18,8 @@ import {
|
|
|
18
18
|
sidebarWidth,
|
|
19
19
|
statusMap,
|
|
20
20
|
batchOpHelpLink,
|
|
21
|
-
modals
|
|
21
|
+
modals,
|
|
22
|
+
fileActions
|
|
22
23
|
} from '../../common/constants'
|
|
23
24
|
import HelpIcon from '../common/help-icon'
|
|
24
25
|
import download from '../../common/download'
|
|
@@ -216,9 +217,7 @@ export default class BatchOp extends PureComponent {
|
|
|
216
217
|
toPath: resolveFilePath(isDown ? conf.localPath : conf.remotePath, name),
|
|
217
218
|
typeFrom: isDown ? 'remote' : 'local',
|
|
218
219
|
typeTo: isDown ? 'local' : 'remote',
|
|
219
|
-
|
|
220
|
-
zip: true,
|
|
221
|
-
skipConfirm: true
|
|
220
|
+
resolvePolicy: fileActions.mergeOrOverwrite
|
|
222
221
|
}
|
|
223
222
|
const { store } = window
|
|
224
223
|
store.addTransferList([obj])
|
|
@@ -229,7 +228,7 @@ export default class BatchOp extends PureComponent {
|
|
|
229
228
|
this.ref1 = autoRun(() => {
|
|
230
229
|
const { transferHistory } = store
|
|
231
230
|
const first = transferHistory.find(t => {
|
|
232
|
-
return
|
|
231
|
+
return t.id === obj.id || t.originalId === obj.id
|
|
233
232
|
})
|
|
234
233
|
if (first && first.sessionId === tab.sessionId) {
|
|
235
234
|
this.ref1 && this.ref1.stop()
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* btns
|
|
3
|
+
*/
|
|
4
|
+
import { Component } from 'react'
|
|
5
|
+
import fs from '../../common/fs'
|
|
6
|
+
import { noTerminalBgValue } from '../../common/constants'
|
|
7
|
+
import { generateMosaicBackground } from './shapes'
|
|
8
|
+
|
|
9
|
+
export default class CssOverwrite extends Component {
|
|
10
|
+
static styleTag = null
|
|
11
|
+
|
|
12
|
+
shouldComponentUpdate (nextProps) {
|
|
13
|
+
if (!this.props.wsInited && nextProps.wsInited) {
|
|
14
|
+
return true
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const bgProps = [
|
|
18
|
+
'terminalBackgroundImagePath',
|
|
19
|
+
'terminalBackgroundFilterBlur',
|
|
20
|
+
'terminalBackgroundFilterOpacity',
|
|
21
|
+
'terminalBackgroundFilterBrightness',
|
|
22
|
+
'terminalBackgroundFilterContrast',
|
|
23
|
+
'terminalBackgroundFilterGrayscale'
|
|
24
|
+
]
|
|
25
|
+
const globalChanged = bgProps.some(prop => this.props[prop] !== nextProps[prop])
|
|
26
|
+
if (globalChanged) {
|
|
27
|
+
return true
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const currentTabs = this.props.tabs || []
|
|
31
|
+
const nextTabs = nextProps.tabs || []
|
|
32
|
+
if (currentTabs.length !== nextTabs.length) {
|
|
33
|
+
return true
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// If no tabs in both cases
|
|
37
|
+
if (!currentTabs.length && !nextTabs.length) {
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Since tab bg settings never change, we only need to compare tab IDs
|
|
42
|
+
const currentIds = new Set(currentTabs.map(t => t.id))
|
|
43
|
+
const nextIds = new Set(nextTabs.map(t => t.id))
|
|
44
|
+
|
|
45
|
+
// Check if all current IDs exist in next IDs
|
|
46
|
+
for (const id of currentIds) {
|
|
47
|
+
if (!nextIds.has(id)) return true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return false
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
componentDidUpdate (prevProps) {
|
|
54
|
+
if (!prevProps.wsInited && this.props.wsInited) {
|
|
55
|
+
this.writeCss()
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
this.updateCss()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Common function to handle background image style creation
|
|
62
|
+
createBackgroundStyle = async (imagePath) => {
|
|
63
|
+
if (!imagePath || imagePath === '') {
|
|
64
|
+
return ''
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let content = ''
|
|
68
|
+
let st = ''
|
|
69
|
+
const isWebImg = /^https?:\/\//.test(imagePath)
|
|
70
|
+
if (imagePath === 'randomShape') {
|
|
71
|
+
st = `url(${generateMosaicBackground()})`
|
|
72
|
+
} else if (imagePath === 'index') {
|
|
73
|
+
st = 'index'
|
|
74
|
+
} else if (noTerminalBgValue === imagePath) {
|
|
75
|
+
st = 'none'
|
|
76
|
+
} else if (imagePath && !isWebImg) {
|
|
77
|
+
content = await fs.readFileAsBase64(imagePath)
|
|
78
|
+
.catch(log.error)
|
|
79
|
+
if (content) {
|
|
80
|
+
st = `url(data:image;base64,${content})`
|
|
81
|
+
}
|
|
82
|
+
} else if (imagePath && isWebImg) {
|
|
83
|
+
st = `url(${imagePath})`
|
|
84
|
+
}
|
|
85
|
+
return st
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Common function to create filter styles
|
|
89
|
+
createFilterStyle = (props, tabProps = null) => {
|
|
90
|
+
return `blur(${
|
|
91
|
+
(tabProps?.terminalBackgroundFilterBlur || props.terminalBackgroundFilterBlur)
|
|
92
|
+
}px) opacity(${
|
|
93
|
+
+(tabProps?.terminalBackgroundFilterOpacity || props.terminalBackgroundFilterOpacity)
|
|
94
|
+
}) brightness(${
|
|
95
|
+
+(tabProps?.terminalBackgroundFilterBrightness || props.terminalBackgroundFilterBrightness)
|
|
96
|
+
}) contrast(${
|
|
97
|
+
+(tabProps?.terminalBackgroundFilterContrast || props.terminalBackgroundFilterContrast)
|
|
98
|
+
}) grayscale(${
|
|
99
|
+
+(tabProps?.terminalBackgroundFilterGrayscale || props.terminalBackgroundFilterGrayscale)
|
|
100
|
+
})`
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
createStyleForTab = async (tab) => {
|
|
104
|
+
const bg = tab.terminalBackground || {}
|
|
105
|
+
const img = bg.terminalBackgroundImagePath || this.props.terminalBackgroundImagePath
|
|
106
|
+
const st = await this.createBackgroundStyle(img)
|
|
107
|
+
|
|
108
|
+
if (!st) {
|
|
109
|
+
return ''
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const selector = `#container .sessions .session-${tab.id} .xterm-screen::before`
|
|
113
|
+
const styles = []
|
|
114
|
+
if (st === 'index') {
|
|
115
|
+
styles.push(`content: '${tab.tabCount}'`)
|
|
116
|
+
} else if (st !== 'none') {
|
|
117
|
+
styles.push(
|
|
118
|
+
`background-image: ${st}`,
|
|
119
|
+
'background-position: center',
|
|
120
|
+
`filter: ${this.createFilterStyle(this.props, tab)}`
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
return `${selector} {
|
|
124
|
+
${styles.join(';')};
|
|
125
|
+
}`
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
createGlobalStyle = async () => {
|
|
129
|
+
const st = await this.createBackgroundStyle(this.props.terminalBackgroundImagePath)
|
|
130
|
+
if (!st) {
|
|
131
|
+
return '#container .session-batch-active .xterm-screen::before {' +
|
|
132
|
+
'background-image: url("./images/electerm-watermark.png");' +
|
|
133
|
+
'}'
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const styles = []
|
|
137
|
+
|
|
138
|
+
if (st !== 'none' && st !== 'index') {
|
|
139
|
+
styles.push(
|
|
140
|
+
`background-image: ${st}`,
|
|
141
|
+
'background-position: center',
|
|
142
|
+
`filter: ${this.createFilterStyle(this.props)}`
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return `#container .session-batch-active .xterm-screen::before {
|
|
147
|
+
${styles.join(';')};
|
|
148
|
+
}`
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
writeCss = async () => {
|
|
152
|
+
if (!CssOverwrite.styleTag) {
|
|
153
|
+
CssOverwrite.styleTag = document.createElement('style')
|
|
154
|
+
CssOverwrite.styleTag.type = 'text/css'
|
|
155
|
+
CssOverwrite.styleTag.id = 'css-overwrite-terminal-backgrounds'
|
|
156
|
+
document.getElementsByTagName('head')[0].appendChild(CssOverwrite.styleTag)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const { tabs = [] } = this.props
|
|
160
|
+
const tabStyles = await Promise.all(
|
|
161
|
+
tabs
|
|
162
|
+
.map(tab => this.createStyleForTab(tab))
|
|
163
|
+
)
|
|
164
|
+
const globalStyle = await this.createGlobalStyle()
|
|
165
|
+
const allStyles = [
|
|
166
|
+
globalStyle,
|
|
167
|
+
...tabStyles
|
|
168
|
+
].filter(Boolean).join('\n')
|
|
169
|
+
CssOverwrite.styleTag.innerHTML = allStyles
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
updateCss = async () => {
|
|
173
|
+
await this.writeCss()
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
render () {
|
|
177
|
+
return null
|
|
178
|
+
}
|
|
179
|
+
}
|