@electerm/electerm-react 5.0.8 → 5.1.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.
Files changed (39) hide show
  1. package/client/common/constants.js +2 -0
  2. package/client/common/default-setting.js +10 -1
  3. package/client/common/left-sidebar-icon-defs.js +36 -0
  4. package/client/components/ai/ai-config-props.js +8 -0
  5. package/client/components/bookmark-form/common/fields.jsx +3 -2
  6. package/client/components/bookmark-form/common/ssh-agent.jsx +3 -2
  7. package/client/components/bookmark-form/common/x11.jsx +2 -2
  8. package/client/components/common/switch.jsx +63 -0
  9. package/client/components/common/switch.styl +7 -0
  10. package/client/components/footer/cmd-history.jsx +4 -8
  11. package/client/components/layout/layout.jsx +8 -5
  12. package/client/components/main/main.jsx +7 -2
  13. package/client/components/profile/profile-form-elem.jsx +2 -2
  14. package/client/components/quick-commands/quick-commands-form-elem.jsx +2 -2
  15. package/client/components/rdp/rdp-session.jsx +3 -4
  16. package/client/components/setting-panel/setting-common.jsx +9 -5
  17. package/client/components/setting-panel/setting-left-sidebar-icons.jsx +54 -0
  18. package/client/components/setting-panel/setting-terminal.jsx +3 -4
  19. package/client/components/setting-sync/data-import.jsx +3 -4
  20. package/client/components/setting-sync/setting-sync-form.jsx +3 -2
  21. package/client/components/sftp/file-compare-modal.jsx +1 -1
  22. package/client/components/sidebar/history.jsx +3 -8
  23. package/client/components/sidebar/index.jsx +22 -71
  24. package/client/components/sidebar/left-sidebar-icons.jsx +148 -0
  25. package/client/components/sidebar/transfer-list.jsx +1 -1
  26. package/client/components/spice/spice-session.jsx +4 -5
  27. package/client/components/terminal/shortcut-bar-defs.js +131 -0
  28. package/client/components/terminal/shortcut-bar-edit.jsx +205 -0
  29. package/client/components/terminal/shortcut-bar-entry.jsx +34 -0
  30. package/client/components/terminal/shortcut-bar.jsx +150 -0
  31. package/client/components/terminal/shortcut-bar.styl +186 -0
  32. package/client/components/terminal/terminal-color-query.mjs +47 -0
  33. package/client/components/terminal/terminal.jsx +39 -1
  34. package/client/components/terminal/terminal.styl +8 -0
  35. package/client/components/terminal-info/base.jsx +5 -7
  36. package/client/components/widgets/widget-form.jsx +3 -2
  37. package/client/store/init-state.js +3 -0
  38. package/client/store/mcp-handler.js +29 -1
  39. package/package.json +1 -1
@@ -79,6 +79,8 @@ export const authTypeMap = buildConst([
79
79
 
80
80
  export const footerHeight = 36
81
81
  export const quickCommandBoxHeight = 180
82
+ export const shortcutBarHeight = 44
83
+ export const shortcutBarLsKey = 'shortcut-bar-buttons'
82
84
  export const isWin = typeof window.et.isWin === 'undefined' ? window.pre.isWin : window.et.isWin
83
85
  export const isMac = typeof window.et.isMac === 'undefined' ? window.pre.isMac : window.et.isMac
84
86
  export const isMacJs = /Macintosh|Mac|Mac OS|MacIntel|MacPPC|Mac68K/gi.test(window.navigator.userAgent)
@@ -79,5 +79,14 @@ export default {
79
79
  allowMultiInstance: false,
80
80
  disableDeveloperTool: false,
81
81
  dragDropBehavior: 'ask',
82
- switchTabOnHover: false
82
+ switchTabOnHover: false,
83
+ leftSideBarIcons: [
84
+ 'newBookmark',
85
+ 'quickConnect',
86
+ 'bookmarks',
87
+ 'terminalThemes',
88
+ 'setting',
89
+ 'settingSync',
90
+ 'widgets'
91
+ ]
83
92
  }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * customizable icons for the far-left sidebar.
3
+ *
4
+ * `text` is a locale key passed to window.translate. The "about",
5
+ * "hide sidebar" and "file transfer" icons are intentionally excluded —
6
+ * they are always visible / conditionally rendered and not part of the
7
+ * customizable set.
8
+ *
9
+ * order of `leftSidebarIconOptions` is the default order shown in the sidebar.
10
+ */
11
+ export const leftSidebarIconOptions = [
12
+ { id: 'newBookmark', text: 'newBookmark' },
13
+ { id: 'quickConnect', text: 'quickConnect' },
14
+ { id: 'bookmarks', text: 'bookmarks' },
15
+ { id: 'terminalThemes', text: 'terminalThemes' },
16
+ { id: 'setting', text: 'setting' },
17
+ { id: 'settingSync', text: 'settingSync' },
18
+ { id: 'widgets', text: 'widgets' }
19
+ ]
20
+
21
+ // default ordered list of icon ids — mirrors the order above
22
+ export const defaultLeftSideBarIcons = leftSidebarIconOptions.map(o => o.id)
23
+
24
+ // valid ids, for sanitizing persisted/synced config
25
+ export const leftSidebarIconIds = new Set(leftSidebarIconOptions.map(o => o.id))
26
+
27
+ /**
28
+ * returns a clean, ordered list of icon ids from a possibly-untrusted value:
29
+ * unknown ids dropped, missing default ids left to the user's choice.
30
+ */
31
+ export function normalizeLeftSideBarIcons (value) {
32
+ if (!Array.isArray(value)) {
33
+ return [...defaultLeftSideBarIcons]
34
+ }
35
+ return value.filter(id => leftSidebarIconIds.has(id))
36
+ }
@@ -19,6 +19,14 @@ export const defaultAIPresets = [
19
19
  modelAI: 'deepseek-ai/deepseek-v4-flash',
20
20
  authHeaderNameAI: 'Authorization: Bearer'
21
21
  },
22
+ {
23
+ id: 'ApiSmart',
24
+ nameAI: 'ApiSmart',
25
+ baseURLAI: 'https://api.apismart.ai/v1',
26
+ apiPathAI: '/chat/completions',
27
+ modelAI: 'DEEPSEEK_V4_FLASH',
28
+ authHeaderNameAI: 'Authorization: Bearer'
29
+ },
22
30
  {
23
31
  id: 'deepseek',
24
32
  nameAI: 'DeepSeek',
@@ -3,9 +3,10 @@
3
3
  * Maps field types to React components
4
4
  */
5
5
  import React from 'react'
6
- import { Form, Input, InputNumber, Switch, Select, AutoComplete, Alert, Radio } from 'antd'
6
+ import { Form, Input, InputNumber, Select, AutoComplete, Alert, Radio } from 'antd'
7
7
  import { ColorPickerItem } from './color-picker-item.jsx'
8
8
  import Password from '../../common/password.jsx'
9
+ import SwitchLabel from '../../common/switch.jsx'
9
10
  import InputAutoFocus from '../../common/input-auto-focus.jsx'
10
11
  import ProxyField from './proxy.jsx'
11
12
  import X11Field from './x11.jsx'
@@ -66,7 +67,7 @@ export function renderFormItem (item, formItemLayout, form, ctxProps, index) {
66
67
  control = <InputNumber min={1} max={65535} step={1} {...item.props} />
67
68
  break
68
69
  case 'switch':
69
- control = <Switch {...item.props} />
70
+ control = <SwitchLabel {...item.props} />
70
71
  break
71
72
  case 'select':
72
73
  control = <Select options={item.options} {...item.props} />
@@ -1,5 +1,6 @@
1
1
  import React from 'react'
2
- import { Form, Input, Switch, Space } from 'antd'
2
+ import { Form, Input, Space } from 'antd'
3
+ import SwitchLabel from '../../common/switch'
3
4
  import HelpIcon from '../../common/help-icon'
4
5
  import { formItemLayout } from '../../../common/form-layout'
5
6
 
@@ -18,7 +19,7 @@ export default function SshAgent () {
18
19
  valuePropName='checked'
19
20
  noStyle
20
21
  >
21
- <Switch />
22
+ <SwitchLabel />
22
23
  </FormItem>
23
24
  <FormItem
24
25
  name='sshAgent'
@@ -2,11 +2,11 @@
2
2
  * bookmark form
3
3
  */
4
4
  import {
5
- Switch,
6
5
  Form,
7
6
  Button,
8
7
  Select
9
8
  } from 'antd'
9
+ import SwitchLabel from '../../common/switch'
10
10
  import { formItemLayout } from '../../../common/form-layout'
11
11
 
12
12
  const FormItem = Form.Item
@@ -153,7 +153,7 @@ export default function renderX11 ({ form }) {
153
153
  name='x11'
154
154
  valuePropName='checked'
155
155
  >
156
- <Switch />
156
+ <SwitchLabel />
157
157
  </FormItem>
158
158
  </>
159
159
  )
@@ -0,0 +1,63 @@
1
+ /**
2
+ * antd Switch wrapper.
3
+ *
4
+ * `checkedChildren` / `unCheckedChildren` cram the label text inside the
5
+ * toggle, which renders poorly on small / touch screens. This wrapper drops
6
+ * those props and renders an optional text label as a sibling `<span>`
7
+ * instead. Clicking the label toggles the switch by default.
8
+ *
9
+ * Passes every other prop (checked, onChange, size, disabled, ref, ...) through
10
+ * to the underlying antd Switch, so it is a drop-in replacement and is safe
11
+ * inside antd Form.Item (`valuePropName='checked'`).
12
+ */
13
+
14
+ import { memo } from 'react'
15
+ import { Switch } from 'antd'
16
+ import './switch.styl'
17
+
18
+ function SwitchLabel (props) {
19
+ const {
20
+ label,
21
+ labelPosition = 'after',
22
+ labelClickToggle = true,
23
+ className = '',
24
+ labelClassName = '',
25
+ checked,
26
+ onChange,
27
+ ref,
28
+ ...rest
29
+ } = props
30
+ const hasLabel = label !== undefined && label !== null && label !== ''
31
+ const onLabelClick = labelClickToggle && onChange
32
+ ? () => onChange(!checked)
33
+ : undefined
34
+ const labelEl = hasLabel
35
+ ? (
36
+ <span
37
+ className={
38
+ 'switch-label-text' +
39
+ (labelPosition === 'before' ? ' mg1r' : ' mg1l') +
40
+ (labelClickToggle ? ' pointer' : '') +
41
+ (labelClassName ? ' ' + labelClassName : '')
42
+ }
43
+ onClick={onLabelClick}
44
+ >
45
+ {label}
46
+ </span>
47
+ )
48
+ : null
49
+ return (
50
+ <span className={'switch-label-wrap' + (className ? ' ' + className : '')}>
51
+ {labelPosition === 'before' ? labelEl : null}
52
+ <Switch
53
+ checked={checked}
54
+ onChange={onChange}
55
+ ref={ref}
56
+ {...rest}
57
+ />
58
+ {labelPosition === 'after' ? labelEl : null}
59
+ </span>
60
+ )
61
+ }
62
+
63
+ export default memo(SwitchLabel)
@@ -0,0 +1,7 @@
1
+ .switch-label-wrap
2
+ display inline-flex
3
+ align-items center
4
+ vertical-align middle
5
+
6
+ .switch-label-text
7
+ user-select none
@@ -3,8 +3,9 @@
3
3
  */
4
4
 
5
5
  import { useState, useEffect } from 'react'
6
- import { Button, Empty, Popover, Switch } from 'antd'
6
+ import { Button, Empty, Popover } from 'antd'
7
7
  import { auto } from 'manate/react'
8
+ import SwitchLabel from '../common/switch'
8
9
  import { copy } from '../../common/clipboard'
9
10
  import { HistoryOutlined, DeleteOutlined, CopyOutlined, UnorderedListOutlined } from '@ant-design/icons'
10
11
  import InputAutoFocus from '../common/input-auto-focus'
@@ -112,17 +113,12 @@ export default auto(function CmdHistory (props) {
112
113
  return (
113
114
  <div className='cmd-history-header pd2b'>
114
115
  <div className='cmd-history-sort'>
115
- <Switch
116
+ <SwitchLabel
116
117
  checked={sortByFrequency}
117
118
  onChange={handleSortByFrequencyChange}
118
119
  size='small'
120
+ label={e('sortByFrequency')}
119
121
  />
120
- <span
121
- className='cmd-history-sort-label pointer'
122
- onClick={() => handleSortByFrequencyChange(!sortByFrequency)}
123
- >
124
- {e('sortByFrequency')}
125
- </span>
126
122
  </div>
127
123
  <UnorderedListOutlined
128
124
  className='cmd-history-clear-icon pointer clear-ai-icon icon-hover'
@@ -4,7 +4,8 @@ import TabsWrap from '../tabs/index'
4
4
  import {
5
5
  splitConfig,
6
6
  quickCommandBoxHeight,
7
- footerHeight
7
+ footerHeight,
8
+ shortcutBarHeight
8
9
  } from '../../common/constants'
9
10
  import layoutAlg from './layout-alg'
10
11
  import calcSessionSize from './session-size-alg'
@@ -41,9 +42,10 @@ export default auto(function Layout (props) {
41
42
  rightPanelPinned,
42
43
  rightPanelWidth,
43
44
  resizeTrigger,
44
- inActiveTerminal
45
+ inActiveTerminal,
46
+ shortcutBarVisible
45
47
  } = props.store
46
- const h = height - footerHeight - (inActiveTerminal && pinnedQuickCommandBar ? quickCommandBoxHeight : 0) + resizeTrigger
48
+ const h = height - footerHeight - (inActiveTerminal && pinnedQuickCommandBar ? quickCommandBoxHeight : 0) - (shortcutBarVisible ? shortcutBarHeight : 0) + resizeTrigger
47
49
  const l = pinned ? leftSideBarWidth + leftSidePanelWidth : leftSideBarWidth
48
50
  const r = rightPanelVisible && rightPanelPinned ? rightPanelWidth : 0
49
51
  return {
@@ -65,14 +67,15 @@ export default auto(function Layout (props) {
65
67
  rightPanelVisible,
66
68
  rightPanelPinned,
67
69
  rightPanelWidth,
68
- pinned
70
+ pinned,
71
+ shortcutBarVisible
69
72
  } = props.store
70
73
  const l = pinned ? leftSidePanelWidth : 0
71
74
  const r = rightPanelPinned && rightPanelVisible ? rightPanelWidth : 0
72
75
  // account for the far-left icon bar (sidebarWidth - 1px border on desktop;
73
76
  // 0 when the bar is hidden on mobile)
74
77
  const w = width - l - r - (leftSideBarWidth > 0 ? leftSideBarWidth - 1 : 0)
75
- const h = height - footerHeight - (pinnedQuickCommandBar ? quickCommandBoxHeight : 0)
78
+ const h = height - footerHeight - (pinnedQuickCommandBar ? quickCommandBoxHeight : 0) - (shortcutBarVisible ? shortcutBarHeight : 0)
76
79
  return layoutAlg(layout, w, h)
77
80
  }
78
81
  const layoutSize = calcLayoutStyle()
@@ -42,6 +42,7 @@ import { pick } from 'lodash-es'
42
42
  import deepCopy from 'json-deep-copy'
43
43
  import './wrapper.styl'
44
44
  import TerminalInfo from '../terminal-info/terminal-info-entry'
45
+ import ShortcutBarEntry from '../terminal/shortcut-bar-entry'
45
46
  import '../../common/fs.js'
46
47
  import './term-fullscreen.styl'
47
48
 
@@ -99,7 +100,8 @@ export default auto(function Index (props) {
99
100
  transferToConfirm,
100
101
  openResolutionEdit,
101
102
  rightPanelTitle,
102
- rightPanelTab
103
+ rightPanelTab,
104
+ widgetInstances
103
105
  } = store
104
106
  const upgradeInfo = deepCopy(store.upgradeInfo)
105
107
  const cls = classnames({
@@ -181,7 +183,9 @@ export default auto(function Index (props) {
181
183
  fileTransfers: copiedTransfer,
182
184
  transferHistory: copiedHistory,
183
185
  upgradeInfo,
184
- pinned
186
+ pinned,
187
+ leftSideBarIcons: config.leftSideBarIcons,
188
+ widgetInstancesLength: widgetInstances.length
185
189
  }
186
190
 
187
191
  const infoModalProps = {
@@ -311,6 +315,7 @@ export default auto(function Index (props) {
311
315
  <BookmarkFromHistoryModal />
312
316
  <NotificationContainer />
313
317
  <BatchOpRunner />
318
+ <ShortcutBarEntry store={store} />
314
319
  {!isAIDisabled() && <AIConfigModal store={store} />}
315
320
  <UnixTimestampTooltip />
316
321
  </div>
@@ -1,10 +1,10 @@
1
1
  import { useState } from 'react'
2
2
  import {
3
3
  Form,
4
- Switch,
5
4
  Button
6
5
  } from 'antd'
7
6
  import message from '../common/message'
7
+ import SwitchLabel from '../common/switch'
8
8
  import InputAutoFocus from '../common/input-auto-focus'
9
9
  import { formItemLayout } from '../../common/form-layout'
10
10
  import HelpIcon from '../common/help-icon'
@@ -90,7 +90,7 @@ export default function ProfileFormElem (props) {
90
90
  name='isDefault'
91
91
  valuePropName='checked'
92
92
  >
93
- <Switch />
93
+ <SwitchLabel />
94
94
  </FormItem>
95
95
  <ProfileTabs {...tabsProps} />
96
96
  <FormItem>
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  Button,
3
- Switch,
4
3
  Form,
5
4
  Select,
6
5
  Input
7
6
  } from 'antd'
8
7
  import message from '../common/message'
8
+ import SwitchLabel from '../common/switch'
9
9
  import { useState } from 'react'
10
10
  import generate from '../../common/uid'
11
11
  import InputAutoFocus from '../common/input-auto-focus'
@@ -162,7 +162,7 @@ export default function QuickCommandForm (props) {
162
162
  name='inputOnly'
163
163
  valuePropName='checked'
164
164
  >
165
- <Switch />
165
+ <SwitchLabel />
166
166
  </FormItem>
167
167
  <FormItem>
168
168
  <p>
@@ -15,7 +15,6 @@ import {
15
15
  import {
16
16
  Spin,
17
17
  Select,
18
- Switch,
19
18
  Tooltip
20
19
  } from 'antd'
21
20
  import * as ls from '../../common/safe-local-storage'
@@ -23,6 +22,7 @@ import scanCode from './code-scan'
23
22
  import resolutions from './resolutions'
24
23
  import { readClipboardAsync } from '../../common/clipboard'
25
24
  import RemoteFloatControl from '../common/remote-float-control'
25
+ import SwitchLabel from '../common/switch'
26
26
  import HelpIcon from '../common/help-icon'
27
27
  import { FileTransferManager, createFileLogger } from './file-transfer'
28
28
  import { notification } from '../common/notification'
@@ -634,8 +634,7 @@ export default class RdpSession extends PureComponent {
634
634
  const scaleProps = {
635
635
  checked: this.state.scaleViewport,
636
636
  onChange: this.handleScaleViewChange,
637
- unCheckedChildren: window.translate('scaleViewport'),
638
- checkedChildren: window.translate('scaleViewport'),
637
+ label: window.translate('scaleViewport'),
639
638
  className: 'mg1l'
640
639
  }
641
640
  const uploadTitle = window.translate('upload') || 'Upload files to remote'
@@ -671,7 +670,7 @@ export default class RdpSession extends PureComponent {
671
670
  className='mg2r mg1l pointer'
672
671
  />
673
672
  {this.renderInfo()}
674
- <Switch
673
+ <SwitchLabel
675
674
  {...scaleProps}
676
675
  />
677
676
  <Tooltip title={uploadTitle}>
@@ -7,9 +7,9 @@ import {
7
7
  } from '@ant-design/icons'
8
8
  import message from '../common/message'
9
9
  import { notification } from '../common/notification'
10
+ import SwitchLabel from '../common/switch'
10
11
  import {
11
12
  Select,
12
- Switch,
13
13
  Button,
14
14
  Table,
15
15
  Space,
@@ -34,6 +34,7 @@ import delay from '../../common/wait.js'
34
34
  import isColorDark from '../../common/is-color-dark'
35
35
  import DeepLinkControl from './deep-link-control'
36
36
  import HotkeySetting from './hotkey'
37
+ import SettingLeftSidebarIcons from './setting-left-sidebar-icons'
37
38
  import './setting.styl'
38
39
 
39
40
  const { Option } = Select
@@ -192,10 +193,9 @@ export default class SettingCommon extends Component {
192
193
  const checked = !!this.props.config[name]
193
194
  return (
194
195
  <div className='pd2b' key={'rt' + name}>
195
- <Switch
196
+ <SwitchLabel
196
197
  checked={checked}
197
- checkedChildren={e(name)}
198
- unCheckedChildren={e(name)}
198
+ label={e(name)}
199
199
  onChange={v => this.onChangeValue(v, name)}
200
200
  />
201
201
  {isNumber(extra) ? null : extra}
@@ -372,7 +372,7 @@ export default class SettingCommon extends Component {
372
372
  style={{ body: { style } }}
373
373
  />
374
374
  </span>
375
- <Switch
375
+ <SwitchLabel
376
376
  checked={enableGlobalProxy}
377
377
  onChange={v => {
378
378
  this.onChangeValue(v, 'enableGlobalProxy')
@@ -471,6 +471,10 @@ export default class SettingCommon extends Component {
471
471
  return (
472
472
  <div className='form-wrap pd1y pd2x'>
473
473
  <h2>{e('settings')}</h2>
474
+ <SettingLeftSidebarIcons
475
+ config={props.config}
476
+ store={props.store}
477
+ />
474
478
  <HotkeySetting
475
479
  {...hotkeyProps}
476
480
  />
@@ -0,0 +1,54 @@
1
+ /**
2
+ * editor (embedded in the common settings page) for the customizable
3
+ * far-left sidebar icons. The select takes effect immediately — order of the
4
+ * selected ids is the order shown in the sidebar.
5
+ */
6
+
7
+ import { Select } from 'antd'
8
+ import {
9
+ leftSidebarIconOptions,
10
+ defaultLeftSideBarIcons
11
+ } from '../../common/left-sidebar-icon-defs'
12
+
13
+ const { Option } = Select
14
+ const e = window.translate
15
+
16
+ export default function SettingLeftSidebarIcons (props) {
17
+ const { config, store } = props
18
+ const value = Array.isArray(config.leftSideBarIcons) && config.leftSideBarIcons.length
19
+ ? config.leftSideBarIcons
20
+ : [...defaultLeftSideBarIcons]
21
+
22
+ const handleChange = (v) => {
23
+ store.updateConfig({
24
+ leftSideBarIcons: v
25
+ })
26
+ }
27
+
28
+ return (
29
+ <div className='pd2b'>
30
+ <div className='pd1b'>{e('leftSideBarIcons')}</div>
31
+ <Select
32
+ mode='multiple'
33
+ value={value}
34
+ onChange={handleChange}
35
+ popupMatchSelectWidth={false}
36
+ style={{ minWidth: 320, width: '100%' }}
37
+ placeholder={e('leftSideBarIcons')}
38
+ >
39
+ {
40
+ leftSidebarIconOptions.map(opt => {
41
+ return (
42
+ <Option
43
+ key={opt.id}
44
+ value={opt.id}
45
+ >
46
+ {e(opt.text)}
47
+ </Option>
48
+ )
49
+ })
50
+ }
51
+ </Select>
52
+ </div>
53
+ )
54
+ }
@@ -4,9 +4,9 @@ import {
4
4
  LoadingOutlined
5
5
  } from '@ant-design/icons'
6
6
  import message from '../common/message'
7
+ import SwitchLabel from '../common/switch'
7
8
  import {
8
9
  Select,
9
- Switch,
10
10
  Button,
11
11
  AutoComplete,
12
12
  Tooltip,
@@ -123,10 +123,9 @@ export default class SettingTerminal extends Component {
123
123
  const txt = label || e(name)
124
124
  return (
125
125
  <div className={cls} key={'rt' + name}>
126
- <Switch
126
+ <SwitchLabel
127
127
  checked={checked}
128
- checkedChildren={txt}
129
- unCheckedChildren={txt}
128
+ label={txt}
130
129
  onChange={v => this.onChangeValue(v, name)}
131
130
  />
132
131
  </div>
@@ -4,7 +4,6 @@
4
4
 
5
5
  import {
6
6
  Button,
7
- Switch,
8
7
  Select,
9
8
  Space
10
9
  } from 'antd'
@@ -13,6 +12,7 @@ import {
13
12
  ExportOutlined
14
13
  } from '@ant-design/icons'
15
14
  import Upload from '../common/upload'
15
+ import SwitchLabel from '../common/switch'
16
16
  import HelpIcon from '../common/help-icon'
17
17
 
18
18
  const e = window.translate
@@ -87,11 +87,10 @@ export default function DataTransport (props) {
87
87
  </Upload>
88
88
  </div>
89
89
  <div className='fright'>
90
- <Switch
90
+ <SwitchLabel
91
91
  checked={autoSyncEnabled}
92
- checkedChildren={txt}
92
+ label={txt}
93
93
  onChange={handleAutoSync}
94
- unCheckedChildren={txt}
95
94
  className='mg3l mg1r'
96
95
  />
97
96
  {autoSyncEnabled && (
@@ -7,8 +7,9 @@
7
7
  */
8
8
  import { useEffect, useRef } from 'react'
9
9
  import { ArrowDownOutlined, ArrowUpOutlined, SaveOutlined, ClearOutlined } from '@ant-design/icons'
10
- import { Button, Input, Form, Alert, Switch } from 'antd'
10
+ import { Button, Input, Form, Alert } from 'antd'
11
11
  import { notification } from '../common/notification'
12
+ import SwitchLabel from '../common/switch'
12
13
  import Link from '../common/external-link'
13
14
  import dayjs from 'dayjs'
14
15
  import eq from 'fast-deep-equal'
@@ -253,7 +254,7 @@ export default function SyncForm (props) {
253
254
  name='skipVerify'
254
255
  valuePropName='checked'
255
256
  >
256
- <Switch />
257
+ <SwitchLabel />
257
258
  </FormItem>
258
259
  <FormItem
259
260
  label={createLabel(e('password'))}
@@ -21,7 +21,7 @@ const formatTime = time
21
21
  const CodeCompare = lazy(() => import('./code-compare'))
22
22
 
23
23
  const Loading = () => (
24
- <div style={{ padding: 40, textAlign: 'center' }}>
24
+ <div className='aligncenter pd3'>
25
25
  <Spin />
26
26
  </div>
27
27
  )
@@ -4,8 +4,8 @@
4
4
 
5
5
  import React, { useState, useEffect } from 'react'
6
6
  import { auto } from 'manate/react'
7
- import { Switch } from 'antd'
8
7
  import { UnorderedListOutlined } from '@ant-design/icons'
8
+ import SwitchLabel from '../common/switch'
9
9
  import HistoryItem from './history-item'
10
10
  import { getItemJSON, setItemJSON } from '../../common/safe-local-storage.js'
11
11
  import '../setting-panel/list.styl'
@@ -45,17 +45,12 @@ export default auto(function HistoryPanel (props) {
45
45
  return (
46
46
  <div className='history-header pd2x pd2b'>
47
47
  <div className='history-sort'>
48
- <Switch
48
+ <SwitchLabel
49
49
  checked={sortByFrequency}
50
50
  onChange={handleSortByFrequencyChange}
51
51
  size='small'
52
+ label={e('sortByFrequency')}
52
53
  />
53
- <span
54
- className='history-sort-label pointer'
55
- onClick={() => handleSortByFrequencyChange(!sortByFrequency)}
56
- >
57
- {e('sortByFrequency')}
58
- </span>
59
54
  </div>
60
55
  <UnorderedListOutlined
61
56
  {...clearIconProps}