@electerm/electerm-react 3.15.159 → 3.15.161
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/components/ai/agent.js +3 -2
- package/client/components/ai/ai-chat-history-item.jsx +2 -1
- package/client/components/ai/ai-chat.jsx +3 -0
- package/client/components/ai/ai-config.jsx +10 -2
- package/client/components/ai/ai-guardrails.js +10 -0
- package/client/components/ai/ai-output.jsx +51 -5
- package/client/components/ai/ai.styl +13 -0
- package/client/components/bookmark-form/ai-bookmark-form.jsx +2 -1
- package/client/components/sftp/address-bar.jsx +39 -5
- package/client/components/sftp/list-table-ui.jsx +19 -2
- package/client/components/sftp/sftp-entry.jsx +1 -1
- package/client/components/sftp/sftp.styl +14 -0
- package/client/components/terminal/terminal-command-dropdown.jsx +2 -1
- package/client/css/mobile.styl +19 -0
- package/client/store/common.js +4 -3
- package/client/store/init-state.js +2 -2
- package/client/store/store.js +18 -1
- package/package.json +1 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { agentTools, executeToolCall } from './agent-tools'
|
|
2
|
+
import { appendMandatoryGuardrails } from './ai-guardrails'
|
|
2
3
|
|
|
3
4
|
const MAX_ITERATIONS = 150
|
|
4
5
|
|
|
5
6
|
function buildAgentSystemPrompt (config) {
|
|
6
7
|
const lang = config.languageAI || window.store.getLangName()
|
|
7
8
|
const baseRole = config.roleAI || 'You are a helpful assistant.'
|
|
8
|
-
return `${baseRole}
|
|
9
|
+
return appendMandatoryGuardrails(`${baseRole}
|
|
9
10
|
|
|
10
11
|
You are operating inside electerm, a terminal/SSH client. You have access to tools that let you:
|
|
11
12
|
- Run commands in terminal tabs and read their output
|
|
@@ -21,7 +22,7 @@ Prefer using the active terminal unless the user specifies otherwise.
|
|
|
21
22
|
For SSH connections, prefer using open_tab to connect directly, or create a bookmark with add_bookmark and open it with open_bookmark if the user wants to save the connection.
|
|
22
23
|
For file transfers, use the sftp_upload and sftp_download tools. The tab must be an SSH/FTP connection with SFTP initialized.
|
|
23
24
|
|
|
24
|
-
Reply in ${lang} language.`
|
|
25
|
+
Reply in ${lang} language.`)
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
function updateChatEntry (chatEntry, updates) {
|
|
@@ -3,6 +3,7 @@ import AIOutput from './ai-output'
|
|
|
3
3
|
import AIStopIcon from './ai-stop-icon'
|
|
4
4
|
import AgentToolCallCard from './agent-tool-call-card'
|
|
5
5
|
import { runAgentLoop } from './agent'
|
|
6
|
+
import { appendMandatoryGuardrails } from './ai-guardrails'
|
|
6
7
|
import {
|
|
7
8
|
Alert,
|
|
8
9
|
Tooltip
|
|
@@ -42,7 +43,7 @@ export default function AIChatHistoryItem ({ item }) {
|
|
|
42
43
|
|
|
43
44
|
function buildRole () {
|
|
44
45
|
const lang = languageAI || window.store.getLangName()
|
|
45
|
-
return roleAI + `;用[${lang}]回复`
|
|
46
|
+
return appendMandatoryGuardrails(roleAI + `;用[${lang}]回复`)
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
const conversationMessages = useMemo(() => {
|
|
@@ -18,6 +18,7 @@ import Password from '../common/password'
|
|
|
18
18
|
import AiHistory, { addHistoryItem } from './ai-history'
|
|
19
19
|
import message from '../common/message'
|
|
20
20
|
import { getAIPresets } from './ai-config-props'
|
|
21
|
+
import { appendMandatoryGuardrails } from './ai-guardrails'
|
|
21
22
|
|
|
22
23
|
const STORAGE_KEY_CONFIG = 'ai_config_history'
|
|
23
24
|
const EVENT_NAME_CONFIG = 'ai-config-history-update'
|
|
@@ -74,7 +75,7 @@ export default function AIConfigForm ({ initialValues, onSubmit, showAIConfig })
|
|
|
74
75
|
'AIchat',
|
|
75
76
|
'Hi',
|
|
76
77
|
values.modelAI,
|
|
77
|
-
values.roleAI,
|
|
78
|
+
appendMandatoryGuardrails(values.roleAI),
|
|
78
79
|
values.baseURLAI,
|
|
79
80
|
values.apiPathAI,
|
|
80
81
|
values.apiKeyAI,
|
|
@@ -164,7 +165,14 @@ export default function AIConfigForm ({ initialValues, onSubmit, showAIConfig })
|
|
|
164
165
|
<Link to={aiConfigWikiLink}>WIKI: {aiConfigWikiLink}</Link>
|
|
165
166
|
}
|
|
166
167
|
type='info'
|
|
167
|
-
className='
|
|
168
|
+
className='mg2t mg1b'
|
|
169
|
+
/>
|
|
170
|
+
<Alert
|
|
171
|
+
title={
|
|
172
|
+
window.translate('aiWarn')
|
|
173
|
+
}
|
|
174
|
+
type='warning'
|
|
175
|
+
className='mg2b'
|
|
168
176
|
/>
|
|
169
177
|
<div className='mg1b alignright'>
|
|
170
178
|
{renderPresetMenu()}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Append mandatory guardrails (if configured via window.et.mandatoryGuardrails)
|
|
2
|
+
// to the AI system role as an extra layer of protection. This is typically set
|
|
3
|
+
// by enterprise deployments to enforce policies on every AI request.
|
|
4
|
+
export function appendMandatoryGuardrails (systemContent) {
|
|
5
|
+
const guardrails = window.et && window.et.mandatoryGuardrails
|
|
6
|
+
if (!guardrails) {
|
|
7
|
+
return systemContent
|
|
8
|
+
}
|
|
9
|
+
return `${systemContent}\n\n${guardrails}`
|
|
10
|
+
}
|
|
@@ -2,12 +2,19 @@ import { useRef, useEffect } from 'react'
|
|
|
2
2
|
import ReactMarkdown from 'react-markdown'
|
|
3
3
|
import { copy } from '../../common/clipboard'
|
|
4
4
|
import Link from '../common/external-link'
|
|
5
|
-
import { Tag } from 'antd'
|
|
6
|
-
import {
|
|
5
|
+
import { Tag, Popconfirm, Button, Alert } from 'antd'
|
|
6
|
+
import {
|
|
7
|
+
CopyOutlined,
|
|
8
|
+
PlayCircleOutlined,
|
|
9
|
+
FlagOutlined,
|
|
10
|
+
FlagFilled
|
|
11
|
+
} from '@ant-design/icons'
|
|
7
12
|
import getBrand from './get-brand'
|
|
8
13
|
|
|
9
14
|
const e = window.translate
|
|
10
15
|
|
|
16
|
+
const enableAIFlag = !!(window.et && window.et.enableAIFlag)
|
|
17
|
+
|
|
11
18
|
export default function AIOutput ({ item }) {
|
|
12
19
|
const outputRef = useRef(null)
|
|
13
20
|
const {
|
|
@@ -23,7 +30,7 @@ export default function AIOutput ({ item }) {
|
|
|
23
30
|
}
|
|
24
31
|
}, [response])
|
|
25
32
|
|
|
26
|
-
if (!response) {
|
|
33
|
+
if (!response && !(item.flagged && enableAIFlag)) {
|
|
27
34
|
return null
|
|
28
35
|
}
|
|
29
36
|
|
|
@@ -89,6 +96,38 @@ export default function AIOutput ({ item }) {
|
|
|
89
96
|
)
|
|
90
97
|
}
|
|
91
98
|
|
|
99
|
+
function handleToggleFlag () {
|
|
100
|
+
const index = window.store.aiChatHistory.findIndex(i => i.id === item.id)
|
|
101
|
+
if (index === -1) {
|
|
102
|
+
return
|
|
103
|
+
}
|
|
104
|
+
window.store.aiChatHistory[index].flagged = !window.store.aiChatHistory[index].flagged
|
|
105
|
+
window.store.aiChatHistory = [...window.store.aiChatHistory]
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function renderFlag () {
|
|
109
|
+
if (!enableAIFlag) {
|
|
110
|
+
return null
|
|
111
|
+
}
|
|
112
|
+
return (
|
|
113
|
+
<div className={'ai-stream-output-flag' + (item.flagged ? ' is-flagged' : '')}>
|
|
114
|
+
<Popconfirm
|
|
115
|
+
title={item.flagged ? 'Remove the harmful-info flag?' : 'Flag this as harmful info?'}
|
|
116
|
+
okText='Confirm'
|
|
117
|
+
cancelText='Cancel'
|
|
118
|
+
onConfirm={handleToggleFlag}
|
|
119
|
+
>
|
|
120
|
+
<Button
|
|
121
|
+
size='small'
|
|
122
|
+
type='text'
|
|
123
|
+
icon={item.flagged ? <FlagFilled /> : <FlagOutlined />}
|
|
124
|
+
onClick={(evt) => evt.stopPropagation()}
|
|
125
|
+
/>
|
|
126
|
+
</Popconfirm>
|
|
127
|
+
</div>
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
|
|
92
131
|
function renderBrand () {
|
|
93
132
|
if (!brand) {
|
|
94
133
|
return null
|
|
@@ -113,9 +152,16 @@ export default function AIOutput ({ item }) {
|
|
|
113
152
|
|
|
114
153
|
return (
|
|
115
154
|
<div className='ai-stream-output' ref={outputRef}>
|
|
155
|
+
{renderFlag()}
|
|
116
156
|
<div className='pd1'>
|
|
117
|
-
{
|
|
118
|
-
|
|
157
|
+
{item.flagged && enableAIFlag
|
|
158
|
+
? <Alert type='warning' message='user flagged as harmful info' />
|
|
159
|
+
: (
|
|
160
|
+
<>
|
|
161
|
+
{renderBrand()}
|
|
162
|
+
<ReactMarkdown {...mdProps} />
|
|
163
|
+
</>
|
|
164
|
+
)}
|
|
119
165
|
</div>
|
|
120
166
|
</div>
|
|
121
167
|
)
|
|
@@ -33,8 +33,17 @@
|
|
|
33
33
|
// display block
|
|
34
34
|
|
|
35
35
|
.ai-stream-output
|
|
36
|
+
position relative
|
|
36
37
|
max-height 400px
|
|
37
38
|
overflow-y auto
|
|
39
|
+
&::-webkit-scrollbar-thumb
|
|
40
|
+
background var(--main-dark)
|
|
41
|
+
.ai-stream-output-flag
|
|
42
|
+
position absolute
|
|
43
|
+
top 13px
|
|
44
|
+
right 10px
|
|
45
|
+
z-index 10
|
|
46
|
+
|
|
38
47
|
|
|
39
48
|
.ai-chat-input
|
|
40
49
|
position relative
|
|
@@ -52,6 +61,9 @@
|
|
|
52
61
|
z-index 1
|
|
53
62
|
font-size 16px
|
|
54
63
|
|
|
64
|
+
.ai-disclamer
|
|
65
|
+
font-size 12px
|
|
66
|
+
|
|
55
67
|
.code-block
|
|
56
68
|
width 100%
|
|
57
69
|
pre
|
|
@@ -69,6 +81,7 @@
|
|
|
69
81
|
|
|
70
82
|
.ai-chat-sessions-wrap
|
|
71
83
|
width 100%
|
|
84
|
+
height 100%
|
|
72
85
|
overflow-y auto
|
|
73
86
|
overflow-x hidden
|
|
74
87
|
padding 4px 0
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
import SimpleEditor from '../text-editor/simple-editor'
|
|
19
19
|
import { copy } from '../../common/clipboard'
|
|
20
20
|
import download from '../../common/download'
|
|
21
|
+
import { appendMandatoryGuardrails } from '../ai/ai-guardrails'
|
|
21
22
|
import AICategorySelect from './common/ai-category-select.jsx'
|
|
22
23
|
import HelpIcon from '../common/help-icon'
|
|
23
24
|
import Modal from '../common/modal.jsx'
|
|
@@ -77,7 +78,7 @@ export default function AIBookmarkForm (props) {
|
|
|
77
78
|
'AIchat',
|
|
78
79
|
prompt,
|
|
79
80
|
config.modelAI,
|
|
80
|
-
'You are a helpful assistant that generates bookmark configurations in JSON format.',
|
|
81
|
+
appendMandatoryGuardrails('You are a helpful assistant that generates bookmark configurations in JSON format.'),
|
|
81
82
|
config.baseURLAI,
|
|
82
83
|
config.apiPathAI,
|
|
83
84
|
config.apiKeyAI,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useRef, useEffect } from 'react'
|
|
1
|
+
import React, { useRef, useEffect, useState } from 'react'
|
|
2
2
|
import {
|
|
3
3
|
ArrowUpOutlined,
|
|
4
4
|
EyeInvisibleFilled,
|
|
@@ -7,11 +7,13 @@ import {
|
|
|
7
7
|
ArrowRightOutlined,
|
|
8
8
|
LoadingOutlined,
|
|
9
9
|
HomeOutlined,
|
|
10
|
-
PlusOutlined
|
|
10
|
+
PlusOutlined,
|
|
11
|
+
MenuOutlined
|
|
11
12
|
} from '@ant-design/icons'
|
|
12
13
|
import {
|
|
13
14
|
Input,
|
|
14
|
-
Tooltip
|
|
15
|
+
Tooltip,
|
|
16
|
+
Popover
|
|
15
17
|
} from 'antd'
|
|
16
18
|
import {
|
|
17
19
|
typeMap
|
|
@@ -22,10 +24,11 @@ import KeywordFilter from './keyword-filter'
|
|
|
22
24
|
|
|
23
25
|
const e = window.translate
|
|
24
26
|
|
|
25
|
-
function
|
|
27
|
+
function AddressPrefixIcons (props) {
|
|
26
28
|
const {
|
|
27
29
|
type,
|
|
28
|
-
host
|
|
30
|
+
host,
|
|
31
|
+
realPath
|
|
29
32
|
} = props
|
|
30
33
|
const isShow = props[`${type}ShowHiddenFile`]
|
|
31
34
|
const title = `${isShow ? e('hide') : e('show')} ${e('hfd')}`
|
|
@@ -75,6 +78,37 @@ function renderAddonBefore (props, realPath) {
|
|
|
75
78
|
)
|
|
76
79
|
}
|
|
77
80
|
|
|
81
|
+
function MobileAddressPrefix (props) {
|
|
82
|
+
const [open, setOpen] = useState(false)
|
|
83
|
+
const content = (
|
|
84
|
+
<div className='sftp-addr-menu-content'>
|
|
85
|
+
<AddressPrefixIcons {...props} />
|
|
86
|
+
</div>
|
|
87
|
+
)
|
|
88
|
+
return (
|
|
89
|
+
<Popover
|
|
90
|
+
content={content}
|
|
91
|
+
trigger='click'
|
|
92
|
+
placement='bottomLeft'
|
|
93
|
+
open={open}
|
|
94
|
+
onOpenChange={setOpen}
|
|
95
|
+
>
|
|
96
|
+
<MenuOutlined className='sftp-addr-menu-icon' />
|
|
97
|
+
</Popover>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function renderAddonBefore (props, realPath) {
|
|
102
|
+
if (window.store.isMobile) {
|
|
103
|
+
return (
|
|
104
|
+
<MobileAddressPrefix {...props} realPath={realPath} />
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
return (
|
|
108
|
+
<AddressPrefixIcons {...props} realPath={realPath} />
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
78
112
|
function renderAddonAfter (isLoadingRemote, onGoto, GoIcon, type, handleUploadFromBrowser) {
|
|
79
113
|
const handleClick = (e) => {
|
|
80
114
|
e.stopPropagation()
|
|
@@ -137,6 +137,23 @@ export default class FileListTable extends Component {
|
|
|
137
137
|
]
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
/**
|
|
141
|
+
* In mobile mode, only show the file name to save horizontal space.
|
|
142
|
+
* Returns the effective properties used for rendering both the
|
|
143
|
+
* table header and individual file items.
|
|
144
|
+
*/
|
|
145
|
+
getRenderProperties = () => {
|
|
146
|
+
if (window.store.isMobile) {
|
|
147
|
+
return [{
|
|
148
|
+
id: 'name',
|
|
149
|
+
max: 98,
|
|
150
|
+
min: 2,
|
|
151
|
+
size: 100
|
|
152
|
+
}]
|
|
153
|
+
}
|
|
154
|
+
return this.state.properties
|
|
155
|
+
}
|
|
156
|
+
|
|
140
157
|
getPropsAll = () => {
|
|
141
158
|
return [
|
|
142
159
|
'name',
|
|
@@ -179,7 +196,7 @@ export default class FileListTable extends Component {
|
|
|
179
196
|
onContextMenu: this.onContextMenu,
|
|
180
197
|
onClickName: this.onClickName,
|
|
181
198
|
onResize: this.onResize,
|
|
182
|
-
properties: this.
|
|
199
|
+
properties: this.getRenderProperties(),
|
|
183
200
|
sortDirection: this.props.sortDirection,
|
|
184
201
|
sortProp: this.props.sortProp,
|
|
185
202
|
maxWidth: this.props.width
|
|
@@ -274,7 +291,7 @@ export default class FileListTable extends Component {
|
|
|
274
291
|
const fileProps = {
|
|
275
292
|
...this.props.getFileProps(item, type),
|
|
276
293
|
cls,
|
|
277
|
-
properties: this.
|
|
294
|
+
properties: this.getRenderProperties(),
|
|
278
295
|
setClickFileId: this.setClickFileId
|
|
279
296
|
}
|
|
280
297
|
return (
|
|
@@ -1211,7 +1211,7 @@ export default class Sftp extends Component {
|
|
|
1211
1211
|
renderSftpPanelTitle (type, username, host) {
|
|
1212
1212
|
if (type === typeMap.remote) {
|
|
1213
1213
|
return (
|
|
1214
|
-
<div className='sftp-panel-title pd1t pd1b pd1x alignright'>
|
|
1214
|
+
<div className='sftp-panel-title pd1t pd1b pd1x alignright elli'>
|
|
1215
1215
|
<ReloadOutlined
|
|
1216
1216
|
className='mg1r pointer'
|
|
1217
1217
|
onClick={this.handleReloadRemoteSftp}
|
|
@@ -185,3 +185,17 @@
|
|
|
185
185
|
&:hover
|
|
186
186
|
&.active
|
|
187
187
|
color var(--success)
|
|
188
|
+
|
|
189
|
+
.sftp-addr-menu-icon
|
|
190
|
+
cursor pointer
|
|
191
|
+
font-size 14px
|
|
192
|
+
color var(--text)
|
|
193
|
+
&:hover
|
|
194
|
+
color var(--text-light)
|
|
195
|
+
|
|
196
|
+
.sftp-addr-menu-content
|
|
197
|
+
display flex
|
|
198
|
+
align-items center
|
|
199
|
+
padding 4px 0
|
|
200
|
+
flex-wrap wrap
|
|
201
|
+
gap 4px
|
|
@@ -2,6 +2,7 @@ import { Component } from 'manate/react/class-components'
|
|
|
2
2
|
import { refsStatic, refs } from '../common/ref'
|
|
3
3
|
import SuggestionItem from './cmd-item'
|
|
4
4
|
import { aiSuggestionsCache } from '../../common/cache'
|
|
5
|
+
import { appendMandatoryGuardrails } from '../ai/ai-guardrails'
|
|
5
6
|
import classnames from 'classnames'
|
|
6
7
|
import {
|
|
7
8
|
LoadingOutlined
|
|
@@ -67,7 +68,7 @@ export default class TerminalCmdSuggestions extends Component {
|
|
|
67
68
|
'AIchat',
|
|
68
69
|
prompt,
|
|
69
70
|
config.modelAI,
|
|
70
|
-
config.roleAI,
|
|
71
|
+
appendMandatoryGuardrails(config.roleAI),
|
|
71
72
|
config.baseURLAI,
|
|
72
73
|
config.apiPathAI,
|
|
73
74
|
config.apiKeyAI,
|
package/client/css/mobile.styl
CHANGED
|
@@ -132,3 +132,22 @@
|
|
|
132
132
|
margin-inline-end 0
|
|
133
133
|
&::before
|
|
134
134
|
display none
|
|
135
|
+
|
|
136
|
+
// ---- 7. Terminal info panel button group: on narrow screens the connected
|
|
137
|
+
// button row in terminal info panel wraps, but antd styles it as a
|
|
138
|
+
// single horizontal strip. When the row wraps, the UI looks broken.
|
|
139
|
+
// Convert each button to a standalone pill so wrapping stays tidy.
|
|
140
|
+
.terminal-info-base
|
|
141
|
+
.ant-space-compact
|
|
142
|
+
display flex
|
|
143
|
+
flex-wrap wrap
|
|
144
|
+
gap 6px
|
|
145
|
+
.ant-btn
|
|
146
|
+
border-radius 3px
|
|
147
|
+
margin-right 0
|
|
148
|
+
|
|
149
|
+
// ---- 8. Upgrade panel: fixed 440px width overflows narrow mobile screens.
|
|
150
|
+
// Constrain it to the viewport minus the right offset (10px) and a
|
|
151
|
+
// matching left gap so it never extends past the screen edge.
|
|
152
|
+
.upgrade-panel
|
|
153
|
+
max-width calc(100vw - 20px)
|
package/client/store/common.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import handleError from '../common/error-handler'
|
|
6
6
|
import Modal from '../components/common/modal'
|
|
7
|
+
import { appendMandatoryGuardrails } from '../components/ai/ai-guardrails'
|
|
7
8
|
import { debounce, some, get, pickBy } from 'lodash-es'
|
|
8
9
|
import {
|
|
9
10
|
leftSidebarWidthKey,
|
|
@@ -106,7 +107,7 @@ export default Store => {
|
|
|
106
107
|
|
|
107
108
|
Store.prototype.setLeftSidePanelWidth = function (v) {
|
|
108
109
|
ls.setItem(leftSidebarWidthKey, v)
|
|
109
|
-
window.store.
|
|
110
|
+
window.store._leftSidebarWidth = v
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
Store.prototype.setAddPanelWidth = function (v) {
|
|
@@ -116,7 +117,7 @@ export default Store => {
|
|
|
116
117
|
|
|
117
118
|
Store.prototype.setRightSidePanelWidth = function (v) {
|
|
118
119
|
ls.setItem(rightSidebarWidthKey, v)
|
|
119
|
-
window.store.
|
|
120
|
+
window.store._rightPanelWidth = v
|
|
120
121
|
}
|
|
121
122
|
Store.prototype.dismissDelKeyTip = function (v) {
|
|
122
123
|
ls.setItem(dismissDelKeyTipLsKey, 'y')
|
|
@@ -322,7 +323,7 @@ export default Store => {
|
|
|
322
323
|
const firstEntry = sessionEntries[0]
|
|
323
324
|
const lang = firstEntry.languageAI || store.getLangName()
|
|
324
325
|
const messages = [
|
|
325
|
-
{ role: 'system', content: firstEntry.roleAI + `;用[${lang}]回复` }
|
|
326
|
+
{ role: 'system', content: appendMandatoryGuardrails(firstEntry.roleAI + `;用[${lang}]回复`) }
|
|
326
327
|
]
|
|
327
328
|
|
|
328
329
|
// Start from the last compress entry to include its summary as context
|
|
@@ -123,7 +123,7 @@ export default () => {
|
|
|
123
123
|
rightPanelVisible: false,
|
|
124
124
|
rightPanelTab: 'info',
|
|
125
125
|
rightPanelPinned: false,
|
|
126
|
-
|
|
126
|
+
_rightPanelWidth: parseInt(ls.getItem(rightSidebarWidthKey), 10) || 500,
|
|
127
127
|
showAIConfigModal: false,
|
|
128
128
|
|
|
129
129
|
// for settings related
|
|
@@ -164,7 +164,7 @@ export default () => {
|
|
|
164
164
|
|
|
165
165
|
// sidebar
|
|
166
166
|
openedSideBar: ls.getItem(openedSidebarKey) || '',
|
|
167
|
-
|
|
167
|
+
_leftSidebarWidth: parseInt(ls.getItem(leftSidebarWidthKey), 10) || 300,
|
|
168
168
|
addPanelWidth: parseInt(ls.getItem(addPanelWidthLsKey), 10) || 300,
|
|
169
169
|
menuOpened: false,
|
|
170
170
|
pinned: ls.getItem(sidebarPinnedKey) === 'true',
|
package/client/store/store.js
CHANGED
|
@@ -37,7 +37,8 @@ import {
|
|
|
37
37
|
terminalSshConfigType,
|
|
38
38
|
paneMap,
|
|
39
39
|
staticNewItemTabs,
|
|
40
|
-
isWin
|
|
40
|
+
isWin,
|
|
41
|
+
sidebarWidth
|
|
41
42
|
} from '../common/constants'
|
|
42
43
|
import getInitItem from '../common/init-setting-item'
|
|
43
44
|
import createTitle from '../common/create-title'
|
|
@@ -58,6 +59,22 @@ class Store {
|
|
|
58
59
|
return window.store.innerWidth
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
get leftSidebarWidth () {
|
|
63
|
+
const { store } = window
|
|
64
|
+
if (store.isMobile) {
|
|
65
|
+
return Math.min(store.innerWidth - sidebarWidth, 500)
|
|
66
|
+
}
|
|
67
|
+
return store._leftSidebarWidth
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get rightPanelWidth () {
|
|
71
|
+
const { store } = window
|
|
72
|
+
if (store.isMobile) {
|
|
73
|
+
return Math.min(store.innerWidth, 500)
|
|
74
|
+
}
|
|
75
|
+
return store._rightPanelWidth
|
|
76
|
+
}
|
|
77
|
+
|
|
61
78
|
get config () {
|
|
62
79
|
return deepCopy(window.store._config)
|
|
63
80
|
}
|