@electerm/electerm-react 5.3.5 → 5.3.15

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.
@@ -29,7 +29,9 @@ import {
29
29
  PlayCircleFilled,
30
30
  StopOutlined,
31
31
  DownloadOutlined,
32
- SwapOutlined
32
+ SwapOutlined,
33
+ PushpinOutlined,
34
+ PushpinFilled
33
35
  } from '@ant-design/icons'
34
36
  import IconHolder from './icon-holder'
35
37
 
@@ -62,5 +64,7 @@ export default {
62
64
  PlayCircleFilled,
63
65
  StopOutlined,
64
66
  DownloadOutlined,
65
- SwapOutlined
67
+ SwapOutlined,
68
+ PushpinOutlined,
69
+ PushpinFilled
66
70
  }
@@ -122,11 +122,23 @@ export default class Tabs extends Component {
122
122
  )
123
123
  }
124
124
 
125
+ // desktop tabs bar renders pinned tabs first: stable partition that keeps
126
+ // the original relative order inside the pinned and unpinned groups.
127
+ // store.tabs order itself is untouched by pinning.
128
+ getSortedTabs = () => {
129
+ const { tabs = [] } = this.props
130
+ return [
131
+ ...tabs.filter(t => t.isPinned),
132
+ ...tabs.filter(t => !t.isPinned)
133
+ ]
134
+ }
135
+
125
136
  adjustScroll = () => {
126
137
  if (this.props.isMobile || !this.domRef.current) {
127
138
  return
128
139
  }
129
- const { tabs, currentBatchTabId, batch } = this.props
140
+ const { currentBatchTabId, batch } = this.props
141
+ const tabs = this.getSortedTabs()
130
142
  const index = tabs.findIndex(t => t.id === currentBatchTabId)
131
143
  const tabsDomWith = Array.from(
132
144
  document.querySelectorAll(`.v${batch + 1} .tab`)
@@ -209,7 +221,7 @@ export default class Tabs extends Component {
209
221
  }
210
222
 
211
223
  renderExtra () {
212
- const items = this.props.tabs.map((t, i) => {
224
+ const items = this.getSortedTabs().map((t, i) => {
213
225
  return {
214
226
  key: i + '##' + t.id,
215
227
  label: (
@@ -261,7 +273,8 @@ export default class Tabs extends Component {
261
273
  }
262
274
 
263
275
  renderContentInner () {
264
- const { tabs = [], width, config } = this.props
276
+ const { width, config } = this.props
277
+ const tabs = this.getSortedTabs()
265
278
  const len = tabs.length
266
279
  const tabsWidthAll = tabMargin * len + 10 + this.tabsWidth()
267
280
  const { overflow } = this.state
@@ -9,7 +9,8 @@ import {
9
9
  CloseOutlined,
10
10
  Loading3QuartersOutlined,
11
11
  BorderlessTableOutlined,
12
- LockOutlined
12
+ LockOutlined,
13
+ PushpinFilled
13
14
  } from '@ant-design/icons'
14
15
  import {
15
16
  Tooltip,
@@ -239,8 +240,15 @@ class Tab extends Component {
239
240
  }
240
241
  }
241
242
 
242
- handleReloadTab = async () => {
243
- window.store.reloadTab(this.props.tab.id)
243
+ handleReloadTab = async (e) => {
244
+ // stop propagation so the parent tab-title click doesn't re-activate
245
+ // this tab by its now-stale (removed) id after reloadTab replaces it
246
+ e && e.stopPropagation()
247
+ const { tab, batch } = this.props
248
+ const newTab = window.store.reloadTab(tab.id)
249
+ if (newTab) {
250
+ window.store.clickTab(newTab.id, batch)
251
+ }
244
252
  }
245
253
 
246
254
  handleReloadAll = () => {
@@ -309,8 +317,13 @@ class Tab extends Component {
309
317
  window.store.closeTabsRight(this.props.tab.id)
310
318
  }
311
319
 
320
+ togglePin = () => {
321
+ const { tab } = this.props
322
+ window.store.pinTab(tab.id, !tab.isPinned)
323
+ }
324
+
312
325
  renderContext = () => {
313
- const { tabs, tabIndex } = this.props
326
+ const { tabs, tabIndex, tab } = this.props
314
327
  const len = tabs.length
315
328
  const index = tabIndex
316
329
  const noRight = index >= len - 1
@@ -359,6 +372,13 @@ class Tab extends Component {
359
372
  icon: <iconsMap.EditOutlined />,
360
373
  label: e('rename')
361
374
  },
375
+ !window.store.isMobile && {
376
+ key: 'togglePin',
377
+ icon: tab.isPinned
378
+ ? <iconsMap.PushpinFilled />
379
+ : <iconsMap.PushpinOutlined />,
380
+ label: tab.isPinned ? e('unpin') : e('pin')
381
+ },
362
382
  {
363
383
  key: 'handleReloadTab',
364
384
  icon: <iconsMap.ReloadOutlined />,
@@ -542,6 +562,7 @@ class Tab extends Component {
542
562
  }
543
563
  <span className='tab-title'>
544
564
  <span className='iblock mg1r tab-count' style={styleTag}>{tabCount}</span>
565
+ {tab.isPinned && <PushpinFilled className='tab-pin' />}
545
566
  <span className='mg1r'>{title}</span>
546
567
  </span>
547
568
  </div>
@@ -225,6 +225,10 @@
225
225
  height 20px
226
226
  line-height 21px
227
227
 
228
+ .tab-pin
229
+ margin-right 3px
230
+ font-size 11px
231
+
228
232
  .ssh-tunnel-list-wrapper
229
233
  max-height 300px
230
234
  overflow-y auto
@@ -29,7 +29,6 @@ import {
29
29
  import * as ls from '../common/safe-local-storage'
30
30
  import { exclude } from 'manate'
31
31
  import initSettingItem from '../common/init-setting-item'
32
- import { getRandomDefaultColor } from '../common/rand-hex-color'
33
32
 
34
33
  const e = window.translate
35
34
 
@@ -39,7 +38,7 @@ function getDefaultBookmarkGroups (bookmarks) {
39
38
  title: e(defaultBookmarkGroupId),
40
39
  id: defaultBookmarkGroupId,
41
40
  bookmarkIds: bookmarks.map(d => d.id),
42
- color: getRandomDefaultColor()
41
+ color: '#0088cc'
43
42
  })
44
43
  ]
45
44
  }
@@ -127,6 +127,8 @@ export default Store => {
127
127
  if (store[batchProp] === tabId) {
128
128
  store[batchProp] = newTab.id
129
129
  }
130
+
131
+ return newTab
130
132
  }
131
133
 
132
134
  Store.prototype.reloadAllTabs = function () {
@@ -168,6 +170,17 @@ export default Store => {
168
170
  store[`activeTabId${sourceTab.batch}`] = duplicatedTab.id
169
171
  }
170
172
 
173
+ // only toggles the flag: the tabs bar renders pinned tabs first,
174
+ // store.tabs order itself is never changed by pinning
175
+ Store.prototype.pinTab = function (tabId, isPinned = true) {
176
+ const { store } = window
177
+ const tab = store.tabs.find(t => t.id === tabId)
178
+ if (!tab || Boolean(tab.isPinned) === isPinned) {
179
+ return
180
+ }
181
+ tab.isPinned = isPinned
182
+ }
183
+
171
184
  Store.prototype.closeOtherTabs = function (id) {
172
185
  const { store } = window
173
186
  const { tabs } = store
@@ -534,7 +547,8 @@ export default Store => {
534
547
  'sshSftpSplitView',
535
548
  'sshTunnelResults',
536
549
  'displayRaw',
537
- 'autoReConnect'
550
+ 'autoReConnect',
551
+ 'isPinned'
538
552
  ]
539
553
  const { history } = store
540
554
  const index = history.filter(d => d.id && d.tab).findIndex(d => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "5.3.5",
3
+ "version": "5.3.15",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",