@electerm/electerm-react 3.15.160 → 3.15.163

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.
@@ -251,6 +251,7 @@ export const checkedKeysLsKey = 'checked-keys'
251
251
  export const quickCommandLabelsLsKey = 'quick-command-label'
252
252
  export const localAddrBookmarkLsKey = 'local-addr-bookmark-keys'
253
253
  export const dismissDelKeyTipLsKey = 'dismiss-del-key-tip'
254
+ export const treeSortLsKey = 'tree-sort'
254
255
  export const sshTunnelHelpLink = 'https://github.com/electerm/electerm/wiki/How-to-use-ssh-tunnel'
255
256
  export const proxyHelpLink = 'https://github.com/electerm/electerm/wiki/proxy-format'
256
257
  export const regexHelpLink = 'https://github.com/electerm/electerm/wiki/Terminal-keywords-highlight-regular-expression-exmaples'
@@ -69,6 +69,23 @@ export async function getLatestReleaseVersion (n) {
69
69
  }
70
70
  }
71
71
 
72
+ export function getDownloadUrl (browserDownloadUrl, mirror) {
73
+ if (!browserDownloadUrl) {
74
+ return ''
75
+ }
76
+ if (mirror === 'gh-proxy') {
77
+ return `https://electerm-mirror.html5beta.com/${browserDownloadUrl}`
78
+ } if (mirror === 'sourceforge') {
79
+ const arr = browserDownloadUrl.split('/')
80
+ const len = arr.length
81
+ return `https://master.dl.sourceforge.net/project/electerm.mirror/${arr[len - 2]}/${arr[len - 1]}?viasf=1`
82
+ } else if (mirror === 'r2') {
83
+ return `https://electerm-store.html5beta.com/r/${browserDownloadUrl.split('/').pop()}`
84
+ } else {
85
+ return browserDownloadUrl
86
+ }
87
+ }
88
+
72
89
  export async function getLatestReleaseInfo () {
73
90
  let url = `${baseUpdateCheckUrls[0]}/data/electerm-github-release.json`
74
91
  let res = await getInfo(url)
@@ -76,10 +93,14 @@ export async function getLatestReleaseInfo () {
76
93
  url = `${baseUpdateCheckUrls[1]}/data/electerm-github-release.json`
77
94
  res = await getInfo(url)
78
95
  }
79
- return res && res.release
80
- ? {
81
- body: res.release.body,
82
- date: dayjs(res.release.published_at).format('YYYY-MM-DD')
83
- }
84
- : undefined
96
+ if (!res || !res.release) {
97
+ return undefined
98
+ }
99
+ const { installSrc } = window.store
100
+ const asset = (res.release.assets || []).find(r => r.name.includes(installSrc))
101
+ return {
102
+ body: res.release.body,
103
+ date: dayjs(res.release.published_at).format('YYYY-MM-DD'),
104
+ browserDownloadUrl: asset ? asset.browser_download_url : ''
105
+ }
85
106
  }
@@ -1,7 +1,7 @@
1
1
  import { PureComponent } from 'react'
2
2
  import { CloseOutlined, MinusSquareOutlined, UpCircleOutlined } from '@ant-design/icons'
3
3
  import { Button, Select, Space } from 'antd'
4
- import { getLatestReleaseInfo, getLatestReleaseVersion } from '../../common/update-check'
4
+ import { getLatestReleaseInfo, getLatestReleaseVersion, getDownloadUrl } from '../../common/update-check'
5
5
  import upgrade from '../../common/upgrade'
6
6
  import compare from '../../common/version-compare'
7
7
  import Link from '../common/external-link'
@@ -136,6 +136,14 @@ export default class Upgrade extends PureComponent {
136
136
  }
137
137
  )
138
138
  }
139
+ if (window.et.downloadUpgradeFromBrowser) {
140
+ const { releaseInfo } = this.props.upgradeInfo
141
+ const downloadUrl = getDownloadUrl(releaseInfo?.browserDownloadUrl, this.state.mirror)
142
+ if (downloadUrl) {
143
+ window.openLink(downloadUrl)
144
+ }
145
+ return
146
+ }
139
147
  this.changeProps({
140
148
  upgrading: true
141
149
  })
@@ -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 renderAddonBefore (props, realPath) {
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.state.properties,
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.state.properties,
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
@@ -9,8 +9,10 @@ import { uniq, filter, pick } from 'lodash-es'
9
9
  import {
10
10
  maxBookmarkGroupTitleLength,
11
11
  defaultBookmarkGroupId,
12
- settingMap
12
+ settingMap,
13
+ treeSortLsKey
13
14
  } from '../../common/constants'
15
+ import { getItemJSON, setItemJSON } from '../../common/safe-local-storage'
14
16
  import findParentBySel from '../../common/find-parent'
15
17
  import copy from 'json-deep-copy'
16
18
  import NewButtonsGroup from './bookmark-toolbar'
@@ -45,7 +47,7 @@ export default class ItemListTree extends Component {
45
47
  categoryColor: '',
46
48
  categoryId: '',
47
49
  searchSelectedRowKey: '',
48
- sort: null
50
+ sort: getItemJSON(treeSortLsKey, null)
49
51
  }
50
52
  this.listRef = React.createRef()
51
53
  }
@@ -111,6 +113,7 @@ export default class ItemListTree extends Component {
111
113
  }
112
114
 
113
115
  handleSortChange = sort => {
116
+ setItemJSON(treeSortLsKey, sort)
114
117
  this.setState({ sort })
115
118
  }
116
119
 
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "3.15.160",
3
+ "version": "3.15.163",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",