@electerm/electerm-react 3.8.8 → 3.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/client/common/parse-quick-connect.js +9 -1
  2. package/client/common/pre.js +0 -1
  3. package/client/components/ai/ai-config-modal.jsx +52 -0
  4. package/client/components/ai/ai-config.jsx +5 -38
  5. package/client/components/ai/get-brand.js +0 -11
  6. package/client/components/bg/custom-css.jsx +2 -1
  7. package/client/components/bookmark-form/bookmark-from-history-modal.jsx +0 -1
  8. package/client/components/bookmark-form/config/rdp.js +4 -2
  9. package/client/components/icons/heartbeat.jsx +23 -0
  10. package/client/components/main/main.jsx +5 -1
  11. package/client/components/session/session.jsx +3 -3
  12. package/client/components/setting-sync/setting-sync-form.jsx +9 -1
  13. package/client/components/setting-sync/setting-sync.jsx +2 -1
  14. package/client/components/sftp/list-table-ui.jsx +29 -54
  15. package/client/components/sftp/paged-list.jsx +44 -44
  16. package/client/components/sftp/sftp-entry.jsx +5 -4
  17. package/client/components/sidebar/info-modal.jsx +8 -2
  18. package/client/components/terminal/reconnect-overlay.jsx +2 -15
  19. package/client/components/terminal/terminal-error-handle.jsx +43 -0
  20. package/client/components/terminal/terminal.jsx +38 -38
  21. package/client/components/terminal/terminal.styl +12 -7
  22. package/client/components/terminal/unix-timestamp-tooltip.jsx +85 -0
  23. package/client/components/tree-list/bookmark-toolbar.jsx +9 -71
  24. package/client/components/tree-list/bookmark-upload.js +106 -0
  25. package/client/components/widgets/widget-control.jsx +1 -0
  26. package/client/store/common.js +3 -11
  27. package/client/store/init-state.js +1 -0
  28. package/client/store/load-data.js +2 -2
  29. package/client/store/sync.js +3 -2
  30. package/client/store/tab.js +20 -0
  31. package/package.json +1 -1
  32. package/client/components/ai/providers.js +0 -14
  33. package/client/components/terminal/socket-close-warning.jsx +0 -94
@@ -16,6 +16,7 @@ import Link from '../common/external-link'
16
16
  import LogoElem from '../common/logo-elem'
17
17
  import RunningTime from './app-running-time'
18
18
  import { auto } from 'manate/react'
19
+ import { useState } from 'react'
19
20
 
20
21
  import {
21
22
  packInfo,
@@ -27,8 +28,13 @@ import './info.styl'
27
28
  const e = window.translate
28
29
 
29
30
  export default auto(function InfoModal (props) {
31
+ const [runtimeEnv, setRuntimeEnv] = useState(null)
32
+
30
33
  const handleChangeTab = key => {
31
34
  window.store.infoModalTab = key
35
+ if (key === infoTabs.env && !runtimeEnv) {
36
+ window.pre.runGlobalAsync('getEnv').then(env => setRuntimeEnv(env))
37
+ }
32
38
  }
33
39
 
34
40
  const renderCheckUpdate = () => {
@@ -135,14 +141,14 @@ export default auto(function InfoModal (props) {
135
141
  knownIssuesLink
136
142
  } = packInfo
137
143
  const link = releaseLink.replace('/releases', '')
138
- const { env, versions } = window.pre
144
+ const { versions } = window.pre
139
145
  const deps = {
140
146
  ...devDependencies,
141
147
  ...dependencies
142
148
  }
143
149
  const envs = {
144
150
  ...versions,
145
- ...env
151
+ ...(runtimeEnv || {})
146
152
  }
147
153
  const title = (
148
154
  <div className='custom-modal-close-confirm-title font16'>
@@ -1,27 +1,14 @@
1
1
  import { memo } from 'react'
2
- import { Button } from 'antd'
3
- import { LoadingOutlined } from '@ant-design/icons'
4
2
 
5
3
  const e = window.translate
6
4
 
7
- export default memo(function ReconnectOverlay ({ countdown, onCancel }) {
5
+ export default memo(function ReconnectOverlay ({ countdown }) {
8
6
  if (countdown === null || countdown === undefined) {
9
7
  return null
10
8
  }
11
9
  return (
12
10
  <div className='terminal-reconnect-overlay'>
13
- <div className='terminal-reconnect-box'>
14
- <LoadingOutlined className='terminal-reconnect-icon' />
15
- <div className='terminal-reconnect-msg'>
16
- {e('autoReconnectTerminal')}: {countdown}s
17
- </div>
18
- <Button
19
- size='small'
20
- onClick={onCancel}
21
- >
22
- {e('cancel')}
23
- </Button>
24
- </div>
11
+ {e('autoReconnectTerminal')}: {countdown}s
25
12
  </div>
26
13
  )
27
14
  })
@@ -0,0 +1,43 @@
1
+ import { memo } from 'react'
2
+ import {
3
+ Button,
4
+ Alert
5
+ } from 'antd'
6
+
7
+ const e = window.translate
8
+
9
+ export default memo(function TerminalErrorHandle ({
10
+ errorMessage,
11
+ showEditBookmarkButton,
12
+ onEditBookmark
13
+ }) {
14
+ if (!errorMessage) {
15
+ return null
16
+ }
17
+
18
+ function renderEditBookmarkButton () {
19
+ if (!showEditBookmarkButton) {
20
+ return null
21
+ }
22
+ return (
23
+ <div className='terminal-error-actions pd1y'>
24
+ <Button
25
+ onClick={onEditBookmark}
26
+ >
27
+ {e('edit')} {e('bookmarks')}
28
+ </Button>
29
+ </div>
30
+ )
31
+ }
32
+
33
+ return (
34
+ <Alert
35
+ className='terminal-error-handle'
36
+ message={errorMessage}
37
+ type='error'
38
+ showIcon
39
+ banner
40
+ description={renderEditBookmarkButton()}
41
+ />
42
+ )
43
+ })
@@ -1,5 +1,4 @@
1
1
  import { Component, createRef } from 'react'
2
- import { handleErr } from '../../common/fetch.jsx'
3
2
  import { isEqual, pick, debounce, throttle } from 'lodash-es'
4
3
  import clone from '../../common/to-simple-obj.js'
5
4
  import resolve from '../../common/resolve.js'
@@ -7,7 +6,6 @@ import {
7
6
  Spin,
8
7
  Dropdown
9
8
  } from 'antd'
10
- import { notification } from '../common/notification'
11
9
  import message from '../common/message'
12
10
  import Modal from '../common/modal'
13
11
  import classnames from 'classnames'
@@ -48,8 +46,8 @@ import ExternalLink from '../common/external-link.jsx'
48
46
  import createDefaultLogPath from '../../common/default-log-path.js'
49
47
  import SearchResultBar from './terminal-search-bar'
50
48
  import RemoteFloatControl from '../common/remote-float-control'
51
- import { showSocketCloseWarning } from './socket-close-warning.jsx'
52
49
  import ReconnectOverlay from './reconnect-overlay.jsx'
50
+ import TerminalErrorHandle from './terminal-error-handle.jsx'
53
51
  import {
54
52
  loadTerminal,
55
53
  loadFitAddon,
@@ -78,6 +76,7 @@ class Term extends Component {
78
76
  matchIndex: -1,
79
77
  totalLines: 0,
80
78
  reconnectCountdown: null,
79
+ terminalError: null,
81
80
  dropFileModalVisible: false,
82
81
  droppedFiles: []
83
82
  }
@@ -169,11 +168,6 @@ class Term extends Component {
169
168
  this.fitAddon = null
170
169
  this.cmdAddon = null
171
170
  this.imageAddon = null
172
- // Clear the notification if it exists
173
- if (this.socketCloseWarning) {
174
- notification.destroy(this.socketCloseWarning.key)
175
- this.socketCloseWarning = null
176
- }
177
171
  }
178
172
 
179
173
  terminalConfigProps = [
@@ -958,9 +952,10 @@ class Term extends Component {
958
952
  }
959
953
 
960
954
  onSelectionChange = () => {
961
- this.setState({
962
- hasSelection: this.term.hasSelection()
963
- })
955
+ const hasSelection = this.term.hasSelection()
956
+ const txt = hasSelection ? this.term.getSelection().trim() : ''
957
+ this.setState({ hasSelection })
958
+ refsStatic.get('unix-timestamp-tooltip')?.onSelection(txt)
964
959
  }
965
960
 
966
961
  // setActive = () => {
@@ -1170,7 +1165,8 @@ class Term extends Component {
1170
1165
 
1171
1166
  remoteInit = async (term = this.term) => {
1172
1167
  this.setState({
1173
- loading: true
1168
+ loading: true,
1169
+ terminalError: null
1174
1170
  })
1175
1171
  const { cols, rows } = term
1176
1172
  const { config } = this.props
@@ -1248,7 +1244,7 @@ class Term extends Component {
1248
1244
  .catch(err => {
1249
1245
  if (!isAutoReconnect) {
1250
1246
  const text = err.message
1251
- handleErr({ message: text })
1247
+ this.handleError({ message: text, from, srcId })
1252
1248
  }
1253
1249
  })
1254
1250
  if (typeof r === 'string' && r.includes('fail')) {
@@ -1304,6 +1300,29 @@ class Term extends Component {
1304
1300
  )
1305
1301
  }
1306
1302
 
1303
+ handleError = ({ message: errorMessage, from, srcId }) => {
1304
+ this.setState({
1305
+ terminalError: {
1306
+ message: errorMessage || 'Failed to create terminal session',
1307
+ from,
1308
+ srcId
1309
+ }
1310
+ })
1311
+ }
1312
+
1313
+ handleEditBookmarkFromError = () => {
1314
+ const error = this.state.terminalError
1315
+ if (!error || error.from !== 'bookmarks' || !error.srcId) {
1316
+ return
1317
+ }
1318
+ const item = window.store.bookmarksMap?.get(error.srcId) ||
1319
+ window.store.bookmarks?.find(d => d.id === error.srcId)
1320
+ if (!item) {
1321
+ return
1322
+ }
1323
+ window.store.openBookmarkEdit(item)
1324
+ }
1325
+
1307
1326
  initSocketEvents = () => {
1308
1327
  const originalSend = this.socket.send
1309
1328
  this.socket.send = (data) => {
@@ -1369,31 +1388,8 @@ class Term extends Component {
1369
1388
  return this.props.delTab(this.props.tab.id)
1370
1389
  }
1371
1390
  const { autoReconnectTerminal } = this.props.config
1372
- const isActive = this.isActiveTerminal()
1373
- const isFocused = window.focused
1374
1391
  if (autoReconnectTerminal) {
1375
- if (isActive && isFocused) {
1376
- this.socketCloseWarning = showSocketCloseWarning({
1377
- tabId: this.props.tab.id,
1378
- tab: this.props.tab,
1379
- autoReconnect: true,
1380
- delTab: this.props.delTab,
1381
- reloadTab: this.props.reloadTab
1382
- })
1383
- } else {
1384
- this.scheduleAutoReconnect(3000)
1385
- }
1386
- } else {
1387
- if (!isActive || !isFocused) {
1388
- return false
1389
- }
1390
- this.socketCloseWarning = showSocketCloseWarning({
1391
- tabId: this.props.tab.id,
1392
- tab: this.props.tab,
1393
- autoReconnect: false,
1394
- delTab: this.props.delTab,
1395
- reloadTab: this.props.reloadTab
1396
- })
1392
+ this.scheduleAutoReconnect(3000)
1397
1393
  }
1398
1394
  }
1399
1395
 
@@ -1547,9 +1543,13 @@ class Term extends Component {
1547
1543
  <RemoteFloatControl
1548
1544
  isFullScreen={fullscreen}
1549
1545
  />
1546
+ <TerminalErrorHandle
1547
+ errorMessage={this.state.terminalError?.message}
1548
+ showEditBookmarkButton={this.state.terminalError?.from === 'bookmarks' && !!this.state.terminalError?.srcId}
1549
+ onEditBookmark={this.handleEditBookmarkFromError}
1550
+ />
1550
1551
  <ReconnectOverlay
1551
1552
  countdown={this.state.reconnectCountdown}
1552
- onCancel={this.handleCancelAutoReconnect}
1553
1553
  />
1554
1554
  <DropFileModal
1555
1555
  visible={this.state.dropFileModalVisible}
@@ -153,12 +153,17 @@
153
153
 
154
154
  .terminal-reconnect-overlay
155
155
  position absolute
156
- left 0
157
- top 0
158
- width 100%
159
- height 100%
160
- display flex
161
- align-items center
162
- justify-content center
156
+ bottom 6px
157
+ right 12px
158
+ font-size 11px
159
+ color rgba(255, 255, 255, 0.55)
160
+ pointer-events none
163
161
  z-index 110
164
162
 
163
+ .terminal-error-handle
164
+ position absolute
165
+ left 0
166
+ top 0
167
+ z-index 100
168
+ background var(--main)
169
+ max-width calc(100% - 24px)
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Global tooltip that detects Unix timestamps in terminal selections
3
+ * and displays their human-readable date/time near the cursor.
4
+ * Registered via refsStatic as 'unix-timestamp-tooltip'.
5
+ */
6
+
7
+ import { Component } from 'react'
8
+ import { refsStatic } from '../common/ref'
9
+
10
+ export default class UnixTimestampTooltip extends Component {
11
+ state = {
12
+ visible: false,
13
+ x: 0,
14
+ y: 0,
15
+ text: ''
16
+ }
17
+
18
+ _mouseX = 0
19
+ _mouseY = 0
20
+
21
+ componentDidMount () {
22
+ refsStatic.add('unix-timestamp-tooltip', this)
23
+ document.addEventListener('mousemove', this.onMouseMove)
24
+ }
25
+
26
+ componentWillUnmount () {
27
+ refsStatic.remove('unix-timestamp-tooltip')
28
+ document.removeEventListener('mousemove', this.onMouseMove)
29
+ }
30
+
31
+ detectUnixTimestamp (txt) {
32
+ if (!/^\d+$/.test(txt)) return null
33
+ const num = parseInt(txt, 10)
34
+ // seconds: 9-10 digits, year ~2001-2286
35
+ if ((txt.length === 9 || txt.length === 10) && num >= 946684800 && num <= 32503680000) {
36
+ return new Date(num * 1000).toLocaleString()
37
+ }
38
+ // milliseconds: 13 digits
39
+ if (txt.length === 13 && num >= 946684800000 && num <= 32503680000000) {
40
+ return new Date(num).toLocaleString()
41
+ }
42
+ return null
43
+ }
44
+
45
+ onMouseMove = (e) => {
46
+ this._mouseX = e.clientX
47
+ this._mouseY = e.clientY
48
+ }
49
+
50
+ onSelection = (txt) => {
51
+ const ts = this.detectUnixTimestamp(txt)
52
+ if (ts) {
53
+ this.setState({ visible: true, x: this._mouseX, y: this._mouseY, text: ts })
54
+ } else {
55
+ this.setState({ visible: false })
56
+ }
57
+ }
58
+
59
+ render () {
60
+ const { visible, x, y, text } = this.state
61
+ if (!visible) {
62
+ return null
63
+ }
64
+ return (
65
+ <div
66
+ style={{
67
+ position: 'fixed',
68
+ left: x,
69
+ top: y - 36,
70
+ background: 'rgba(0,0,0,0.75)',
71
+ color: '#fff',
72
+ padding: '3px 8px',
73
+ borderRadius: 4,
74
+ fontSize: 12,
75
+ whiteSpace: 'nowrap',
76
+ pointerEvents: 'none',
77
+ transform: 'translateX(-50%)',
78
+ zIndex: 9999
79
+ }}
80
+ >
81
+ {text}
82
+ </div>
83
+ )
84
+ }
85
+ }
@@ -7,15 +7,12 @@ import {
7
7
  MenuOutlined,
8
8
  EditOutlined
9
9
  } from '@ant-design/icons'
10
- import { Button, Space, Dropdown } from 'antd'
10
+ import { Button, Space, Dropdown, Flex } from 'antd'
11
11
  import copy from 'json-deep-copy'
12
12
  import time from '../../common/time'
13
- import { uniq } from 'lodash-es'
14
- import { fixBookmarks } from '../../common/db-fix'
15
13
  import download from '../../common/download'
16
- import delay from '../../common/wait'
17
- import { action } from 'manate'
18
14
  import Upload from '../common/upload'
15
+ import { beforeBookmarkUpload } from './bookmark-upload'
19
16
 
20
17
  const e = window.translate
21
18
 
@@ -28,71 +25,12 @@ export default function BookmarkToolbar (props) {
28
25
  bookmarkGroups,
29
26
  bookmarks
30
27
  } = props
31
- const upload = action(async (file) => {
32
- const { store } = window
33
- const filePath = file.filePath
34
- const txt = await window.fs.readFile(filePath)
35
-
36
- const content = JSON.parse(txt)
37
- const {
38
- bookmarkGroups: bookmarkGroups1,
39
- bookmarks: bookmarks1
40
- } = content
41
- const bookmarkGroups0 = copy(bookmarkGroups)
42
- const bookmarks0 = copy(bookmarks)
43
-
44
- // Using Map instead of reduce
45
- const bmTree = new Map(
46
- bookmarks0.map(bookmark => [bookmark.id, bookmark])
47
- )
48
- const bmgTree = new Map(
49
- bookmarkGroups0.map(group => [group.id, group])
50
- )
51
-
52
- const fixed = fixBookmarks(bookmarks1)
53
-
54
- fixed.forEach(bg => {
55
- if (!bmTree.has(bg.id)) {
56
- store.bookmarks.push(bg)
57
- }
58
- })
59
-
60
- bookmarkGroups1.forEach(bg => {
61
- if (!bmgTree.has(bg.id)) {
62
- store.bookmarkGroups.push(bg)
63
- } else {
64
- const bg1 = store.bookmarkGroups.find(
65
- b => b.id === bg.id
66
- )
67
- bg1.bookmarkIds = uniq(
68
- [
69
- ...bg1.bookmarkIds,
70
- ...bg.bookmarkIds
71
- ]
72
- )
73
- }
74
- })
75
- return false
76
- })
77
- const beforeUpload = async (file) => {
78
- const names = [
79
- 'bookmarks',
80
- 'bookmarkGroups'
81
- ]
82
- for (const name of names) {
83
- window[`watch${name}`].stop()
84
- }
85
- upload(file)
86
- await delay(1000)
87
- for (const name of names) {
88
- window[`watch${name}`].start()
89
- }
90
- }
28
+ const beforeUpload = beforeBookmarkUpload
91
29
 
92
30
  const handleDownload = () => {
93
31
  const txt = JSON.stringify({
94
- bookmarkGroups: copy(bookmarkGroups),
95
- bookmarks: copy(bookmarks)
32
+ bookmarkGroups: copy(bookmarkGroups || []),
33
+ bookmarks: copy(bookmarks || [])
96
34
  }, null, 2)
97
35
  const stamp = time(undefined, 'YYYY-MM-DD-HH-mm-ss')
98
36
  download('bookmarks-' + stamp + '.json', txt)
@@ -149,8 +87,8 @@ export default function BookmarkToolbar (props) {
149
87
  return (
150
88
 
151
89
  <div className='pd1b pd1r'>
152
- <div className='fix'>
153
- <div className='fleft'>
90
+ <Flex justify='space-between' align='center'>
91
+ <div>
154
92
  <Space.Compact>
155
93
  <Button onClick={onNewBookmark}>
156
94
  <BookOutlined className='with-plus' />
@@ -184,12 +122,12 @@ export default function BookmarkToolbar (props) {
184
122
  </Button>
185
123
  </Space.Compact>
186
124
  </div>
187
- <div className='fright'>
125
+ <div>
188
126
  <Dropdown {...ddProps}>
189
127
  <MenuOutlined />
190
128
  </Dropdown>
191
129
  </div>
192
- </div>
130
+ </Flex>
193
131
  </div>
194
132
  )
195
133
  }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * bookmark import/upload logic
3
+ */
4
+
5
+ import copy from 'json-deep-copy'
6
+ import { uniq, isPlainObject } from 'lodash-es'
7
+ import { action } from 'manate'
8
+ import uid from '../../common/uid'
9
+ import time from '../../common/time'
10
+ import { fixBookmarks } from '../../common/db-fix'
11
+ import delay from '../../common/wait'
12
+
13
+ function fixBookmarksId (bookmarks) {
14
+ return bookmarks.map(item => {
15
+ if (!isPlainObject(item)) {
16
+ return null
17
+ }
18
+ if (!item.id) {
19
+ item.id = uid()
20
+ }
21
+ return item
22
+ }).filter(Boolean)
23
+ }
24
+ export const bookmarkUpload = action(async (file) => {
25
+ const { store } = window
26
+ const { bookmarks, bookmarkGroups } = store
27
+
28
+ const filePath = file.filePath
29
+ const txt = await window.fs.readFile(filePath)
30
+
31
+ const content = JSON.parse(txt)
32
+ let bookmarkGroups1 = []
33
+ let bookmarks1 = []
34
+ if (Array.isArray(content)) {
35
+ bookmarks1 = fixBookmarksId(content)
36
+ bookmarkGroups1 = [{
37
+ id: uid(),
38
+ title: 'imported_' + time(),
39
+ color: '#0088cc',
40
+ bookmarkGroupIds: [],
41
+ bookmarkIds: bookmarks1.map(b => b.id)
42
+ }]
43
+ } else {
44
+ bookmarkGroups1 = content.bookmarkGroups || []
45
+ bookmarks1 = fixBookmarksId(content.bookmarks || [])
46
+ }
47
+
48
+ const bookmarkGroups0 = copy(bookmarkGroups)
49
+ const bookmarks0 = copy(bookmarks)
50
+
51
+ const bmTree = new Map(
52
+ bookmarks0.map(bookmark => [bookmark.id, bookmark])
53
+ )
54
+ const bmgTree = new Map(
55
+ bookmarkGroups0.map(group => [group.id, group])
56
+ )
57
+
58
+ const fixed = fixBookmarks(bookmarks1)
59
+
60
+ fixed.forEach(bg => {
61
+ if (!bmTree.has(bg.id)) {
62
+ store.bookmarks.push(bg)
63
+ }
64
+ })
65
+
66
+ bookmarkGroups1.forEach(bg => {
67
+ if (!bmgTree.has(bg.id)) {
68
+ store.bookmarkGroups.push(bg)
69
+ } else {
70
+ const bg1 = store.bookmarkGroups.find(
71
+ b => b.id === bg.id
72
+ )
73
+ bg1.bookmarkIds = uniq(
74
+ [
75
+ ...(bg1.bookmarkIds || []),
76
+ ...(bg.bookmarkIds || [])
77
+ ]
78
+ )
79
+ bg1.bookmarkGroupIds = uniq(
80
+ [
81
+ ...(bg1.bookmarkGroupIds || []),
82
+ ...(bg.bookmarkGroupIds || [])
83
+ ]
84
+ )
85
+ }
86
+ })
87
+
88
+ store.fixBookmarkGroups()
89
+
90
+ return false
91
+ })
92
+
93
+ export async function beforeBookmarkUpload (file) {
94
+ const names = [
95
+ 'bookmarks',
96
+ 'bookmarkGroups'
97
+ ]
98
+ for (const name of names) {
99
+ window[`watch${name}`].stop()
100
+ }
101
+ bookmarkUpload(file)
102
+ await delay(1000)
103
+ for (const name of names) {
104
+ window[`watch${name}`].start()
105
+ }
106
+ }
@@ -55,6 +55,7 @@ export default function WidgetControl ({ formData, widgetInstancesLength }) {
55
55
  showMsg(msg, 'success', result.serverInfo, 10)
56
56
  } catch (err) {
57
57
  console.error('Failed to run widget:', err)
58
+ showMsg(`Failed to run widget: ${err.message}`, 'error', null, 10)
58
59
  } finally {
59
60
  setLoading(false)
60
61
  }
@@ -10,9 +10,7 @@ import {
10
10
  rightSidebarWidthKey,
11
11
  addPanelWidthLsKey,
12
12
  dismissDelKeyTipLsKey,
13
- connectionMap,
14
- settingMap,
15
- settingAiId
13
+ connectionMap
16
14
  } from '../common/constants'
17
15
  import * as ls from '../common/safe-local-storage'
18
16
  import { refs, refsStatic } from '../components/common/ref'
@@ -20,7 +18,6 @@ import { action } from 'manate'
20
18
  import uid from '../common/uid'
21
19
  import deepCopy from 'json-deep-copy'
22
20
  import { aiConfigsArr } from '../components/ai/ai-config-props'
23
- import settingList from '../common/setting-list'
24
21
 
25
22
  const e = window.translate
26
23
  const { assign } = Object
@@ -54,12 +51,7 @@ export default Store => {
54
51
  }
55
52
 
56
53
  Store.prototype.toggleAIConfig = function () {
57
- const { store } = window
58
- store.storeAssign({
59
- settingTab: settingMap.setting
60
- })
61
- store.setSettingItem(settingList().find(d => d.id === settingAiId))
62
- store.openSettingModal()
54
+ window.store.showAIConfigModal = true
63
55
  }
64
56
 
65
57
  Store.prototype.onResize = debounce(async function () {
@@ -306,7 +298,7 @@ export default Store => {
306
298
  }
307
299
 
308
300
  Store.prototype.aiConfigMissing = function () {
309
- return aiConfigsArr.slice(0, -1).some(k => !window.store.config[k])
301
+ return aiConfigsArr.filter(k => k !== 'apiKeyAI' && k !== 'proxyAI').some(k => !window.store.config[k])
310
302
  }
311
303
 
312
304
  Store.prototype.clearHistory = function () {
@@ -118,6 +118,7 @@ export default () => {
118
118
  rightPanelTab: 'info',
119
119
  rightPanelPinned: false,
120
120
  rightPanelWidth: parseInt(ls.getItem(rightSidebarWidthKey), 10) || 500,
121
+ showAIConfigModal: false,
121
122
 
122
123
  // for settings related
123
124
  settingItem: initSettingItem([], settingMap.bookmarks),
@@ -100,7 +100,7 @@ export async function addTabFromCommandLine (store, opts) {
100
100
  (conf.username && conf.host) ||
101
101
  conf.fromCmdLine
102
102
  ) {
103
- store.addTab(conf)
103
+ store.ipcOpenTab(conf)
104
104
  } else if (
105
105
  options.initFolder &&
106
106
  !(store.config.onStartSessions || []).length &&
@@ -229,7 +229,7 @@ export default (Store) => {
229
229
  Store.prototype.checkPendingDeepLink = async function () {
230
230
  const pending = await window.pre.runGlobalAsync('getPendingDeepLink')
231
231
  if (pending) {
232
- window.store.addTab(pending)
232
+ window.store.ipcOpenTab(pending)
233
233
  }
234
234
  }
235
235
  Store.prototype.parseQuickConnect = function (url) {
@@ -68,11 +68,12 @@ export default (Store) => {
68
68
  ).join('####')
69
69
  }
70
70
  if (type === syncTypes.webdav) {
71
- // WebDAV token format: serverUrl####username####password
71
+ // WebDAV token format: serverUrl####username####password####skipVerify
72
72
  const serverUrl = get(window.store.config, 'syncSetting.webdavServerUrl')
73
73
  const username = get(window.store.config, 'syncSetting.webdavUsername')
74
74
  const password = get(window.store.config, 'syncSetting.webdavPassword')
75
- return [serverUrl, username, password].join('####')
75
+ const skipVerify = get(window.store.config, 'syncSetting.webdavSkipVerify') || false
76
+ return [serverUrl, username, password, skipVerify].join('####')
76
77
  }
77
78
  return get(window.store.config, 'syncSetting.' + type + 'AccessToken')
78
79
  }