@@ -22,6 +22,7 @@ import Icons from '../spi/Icons'
22
22
import KuiContext from './context'
23
23
import Confirm from '../Views/Confirm'
24
24
import Loading from '../spi/Loading'
25
+ import { TopTabButton } from './TabModel'
25
26
import Width from '../Views/Sidecar/width'
26
27
import WatchPane , { Height } from '../Views/WatchPane'
27
28
@@ -53,6 +54,7 @@ type Props = TabContentOptions &
53
54
active : boolean
54
55
state : TabState
55
56
onTabReady ?: ( tab : KuiTab ) => void
57
+ willUpdateTopTabButtons ?: ( buttons : TopTabButton [ ] ) => void
56
58
}
57
59
58
60
type CurrentlyShowing = 'TerminalOnly' | 'TerminalPlusSidecar' | 'TerminalPlusWatcher' | 'TerminalSidecarWatcher'
@@ -274,7 +276,7 @@ export default class TabContent extends React.PureComponent<Props, State> {
274
276
const sidecarWidth = desiredWidth
275
277
const watchPaneOpen = curState . primaryHeight === Height . Split
276
278
277
- const activeView =
279
+ const activeView : CurrentlyShowing =
278
280
sidecarWidth === Width . Closed
279
281
? watchPaneOpen
280
282
? 'TerminalPlusWatcher'
@@ -283,12 +285,15 @@ export default class TabContent extends React.PureComponent<Props, State> {
283
285
? 'TerminalSidecarWatcher'
284
286
: 'TerminalPlusSidecar'
285
287
286
- return {
288
+ const newState = {
287
289
sidecarHasContent : true ,
288
290
sidecarWidth,
289
291
priorSidecarWidth : curState . sidecarWidth ,
290
292
activeView
291
293
}
294
+
295
+ this . updateTopTabButtons ( newState )
296
+ return newState
292
297
} )
293
298
}
294
299
@@ -300,10 +305,26 @@ export default class TabContent extends React.PureComponent<Props, State> {
300
305
const sidecarWidth = showSidecar ? Width . Split60 : Width . Closed
301
306
const primaryHeight = showWatchPane ? Height . Split : Height . NotSplit
302
307
303
- return { sidecarWidth, activeView, priorSidecarWidth : curState . sidecarWidth , primaryHeight }
308
+ const newState = {
309
+ sidecarWidth,
310
+ activeView,
311
+ priorSidecarWidth : curState . sidecarWidth ,
312
+ primaryHeight,
313
+ sidecarHasContent : curState . sidecarHasContent
314
+ }
315
+
316
+ this . updateTopTabButtons ( newState )
317
+ return newState
304
318
} )
305
319
}
306
320
321
+ /** Switch to the given view, if we aren't already there */
322
+ private showIfNot ( desiredView : CurrentlyShowing ) {
323
+ if ( this . state . activeView !== desiredView ) {
324
+ this . show ( desiredView )
325
+ }
326
+ }
327
+
307
328
private openWatchPane ( ) {
308
329
const notWatching = this . state . activeView === 'TerminalOnly' || this . state . activeView === 'TerminalPlusSidecar'
309
330
@@ -444,8 +465,6 @@ export default class TabContent extends React.PureComponent<Props, State> {
444
465
</ div >
445
466
{ this . state . tab && < Confirm tab = { this . state . tab } uuid = { this . props . uuid } /> }
446
467
</ div >
447
-
448
- { this . topTabButtons ( ) }
449
468
</ React . Fragment >
450
469
)
451
470
}
@@ -505,62 +524,56 @@ export default class TabContent extends React.PureComponent<Props, State> {
505
524
}
506
525
507
526
/**
508
- * Buttons that are placed in the TopTabStripe and which controller
509
- * the visibility of various views.
527
+ * If given, use the top tab button controller to provide the
528
+ * latest button model.
529
+ *
510
530
*/
511
- protected topTabButtons ( ) {
512
- if ( this . props . active && ( this . state . sidecarHasContent || this . state . watchPaneHasContent ) ) {
513
- const buttonNum = this . state . sidecarHasContent && this . state . watchPaneHasContent ? 4 : 2
531
+ private updateTopTabButtons ( newState : Pick < State , 'activeView' | 'sidecarHasContent' > ) {
532
+ if ( this . props . willUpdateTopTabButtons ) {
533
+ this . props . willUpdateTopTabButtons ( [ this . terminalButton ( newState ) , this . sidecarButton ( newState ) ] . filter ( _ => _ ) )
534
+ }
535
+ }
514
536
515
- return (
516
- < div
517
- id = "kui--custom-top-tab-stripe-button-container"
518
- num-button = { buttonNum } // helps with css to calculate the right position of the container
519
- className = "kui--hide-in-narrower-windows" // re: kui--hide-in-narrower-windows, see https://github.com/IBM/kui/issues/4459
520
- >
537
+ /**
538
+ * Note how we use the argument `state` to initialize things, but we
539
+ * intentionally use this.state in the onClick. The onClick handler
540
+ * may be invoked after any number of onClicks in this or other
541
+ * buttons. So it must pay attention to the *current* state, not the
542
+ * state at the time of creation.
543
+ *
544
+ */
545
+ private terminalButton ( state : Pick < State , 'activeView' > ) : TopTabButton {
546
+ const key = 'show only terminal'
547
+
548
+ return {
549
+ icon : (
550
+ < Icons
551
+ icon = "TerminalOnly"
552
+ key = { key }
553
+ data-mode = { key }
554
+ data-active = { state . activeView === 'TerminalOnly' || undefined }
555
+ onClick = { this . showIfNot . bind ( this , 'TerminalOnly' ) }
556
+ />
557
+ )
558
+ }
559
+ }
560
+
561
+ /** Caution: see the Note for this.terminalButton, re: `state` versus `this.state` */
562
+ private sidecarButton ( state : Pick < State , 'activeView' | 'sidecarHasContent' > ) : TopTabButton {
563
+ if ( state . sidecarHasContent ) {
564
+ const key = 'show terminal and sidecar'
565
+
566
+ return {
567
+ icon : (
521
568
< Icons
522
- icon = "TerminalOnly"
523
- data-mode = "show only terminal"
524
- data-active = { this . state . activeView === 'TerminalOnly' || undefined }
525
- onClick = { this . state . activeView !== 'TerminalOnly' ? ( ) => this . show ( 'TerminalOnly' ) : undefined }
569
+ icon = "TerminalPlusSidecar"
570
+ key = { key }
571
+ data-mode = { key }
572
+ data-active = { state . activeView === 'TerminalPlusSidecar' || undefined }
573
+ onClick = { this . showIfNot . bind ( this , 'TerminalPlusSidecar' ) }
526
574
/>
527
-
528
- { this . state . sidecarHasContent && (
529
- < Icons
530
- icon = "TerminalPlusSidecar"
531
- data-mode = "show terminal and sidecar"
532
- data-active = { this . state . activeView === 'TerminalPlusSidecar' || undefined }
533
- onClick = {
534
- this . state . activeView !== 'TerminalPlusSidecar' ? ( ) => this . show ( 'TerminalPlusSidecar' ) : undefined
535
- }
536
- />
537
- ) }
538
-
539
- { this . state . watchPaneHasContent && (
540
- < Icons
541
- icon = "TerminalPlusWatcher"
542
- data-mode = "show terminal and watcher"
543
- data-active = { this . state . activeView === 'TerminalPlusWatcher' || undefined }
544
- onClick = {
545
- this . state . activeView !== 'TerminalPlusWatcher' ? ( ) => this . show ( 'TerminalPlusWatcher' ) : undefined
546
- }
547
- />
548
- ) }
549
-
550
- { this . state . watchPaneHasContent && this . state . sidecarHasContent && (
551
- < Icons
552
- icon = "TerminalSidecarWatcher"
553
- data-mode = "show terminal sidecar and watcher"
554
- data-active = { this . state . activeView === 'TerminalSidecarWatcher' || undefined }
555
- onClick = {
556
- this . state . activeView !== 'TerminalSidecarWatcher'
557
- ? ( ) => this . show ( 'TerminalSidecarWatcher' )
558
- : undefined
559
- }
560
- />
561
- ) }
562
- </ div >
563
- )
575
+ )
576
+ }
564
577
}
565
578
}
566
579
}
0 commit comments