Skip to content
This repository was archived by the owner on Jul 30, 2025. It is now read-only.

Commit 09f9b7d

Browse files
committed
fix(plugins/plugin-client-common): tab switching can be slow on windows
Fixes #5907
1 parent 7278d8a commit 09f9b7d

File tree

3 files changed

+40
-25
lines changed

3 files changed

+40
-25
lines changed

plugins/plugin-client-common/src/components/Views/Terminal/ScrollableTerminal.tsx

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ export default class ScrollableTerminal extends React.PureComponent<Props, State
188188
: { name: this.props.tabTitle, description: '', splits: [this.scrollbackWithWelcome()] }
189189

190190
this.state = {
191-
focusedIdx: 0,
191+
focusedIdx: -1,
192192
splits,
193193
notebookMetadata: { name, description }
194194
}
@@ -621,24 +621,43 @@ export default class ScrollableTerminal extends React.PureComponent<Props, State
621621
}
622622

623623
/** Owner wants us to focus on the current prompt */
624-
public doFocus(scrollback = this.current) {
625-
const { _activeBlock } = scrollback
624+
private _focusDebouncer: NodeJS.Timeout
625+
public doFocus(scrollback = this.current, idx = this.state.focusedIdx) {
626+
if (this.state.focusedIdx >= 0 && idx === this.state.focusedIdx) {
627+
return
628+
}
629+
630+
if (this._focusDebouncer) {
631+
clearTimeout(this._focusDebouncer)
632+
this._focusDebouncer = undefined
633+
}
626634

627-
if (_activeBlock) {
628-
if (_activeBlock.state._block && isInViewport(_activeBlock.state._block)) {
629-
// re: isInViewport, see https://github.com/IBM/kui/issues/4739
630-
_activeBlock.doFocus()
635+
const ourDebouncer = setTimeout(() => {
636+
if (this._focusDebouncer !== ourDebouncer || (this.state.focusedIdx >= 0 && idx === this.state.focusedIdx)) {
637+
return
638+
} else {
639+
this._focusDebouncer = undefined
631640
}
632-
} else {
633-
// a bit of a data abstraction violation; we should figure out how to solve this better
634-
// see https://github.com/IBM/kui/issues/3945
635-
const xterm = document.querySelector('textarea.xterm-helper-textarea') as HTMLTextAreaElement
636-
if (xterm) {
637-
xterm.focus()
641+
642+
const { _activeBlock } = scrollback
643+
644+
if (_activeBlock) {
645+
if (_activeBlock.state._block && isInViewport(_activeBlock.state._block)) {
646+
// re: isInViewport, see https://github.com/IBM/kui/issues/4739
647+
_activeBlock.doFocus()
648+
}
649+
} else {
650+
// a bit of a data abstraction violation; we should figure out how to solve this better
651+
// see https://github.com/IBM/kui/issues/3945
652+
const xterm = document.querySelector('textarea.xterm-helper-textarea') as HTMLTextAreaElement
653+
if (xterm) {
654+
xterm.focus()
655+
}
638656
}
639-
}
640657

641-
this.setFocusOnScrollback(scrollback)
658+
this.setFocusOnScrollback(scrollback)
659+
}, 10)
660+
this._focusDebouncer = ourDebouncer
642661
}
643662

644663
/**
@@ -866,7 +885,7 @@ export default class ScrollableTerminal extends React.PureComponent<Props, State
866885
eventBus.emitWithTabId('/tab/close/request', parent.uuid, parent)
867886
}
868887

869-
return { splits }
888+
return { splits, focusedIdx: idx === 0 ? 0 : idx - 1 }
870889
}
871890
})
872891
}
@@ -1124,7 +1143,7 @@ export default class ScrollableTerminal extends React.PureComponent<Props, State
11241143
willRemove={this.willRemoveBlock.bind(this, scrollback.uuid, idx)}
11251144
hasBlockAfter={this.hasBlockAfter(scrollback.blocks, idx)}
11261145
hasBlockBefore={this.hasBlockBefore(idx)}
1127-
willLoseFocus={() => this.doFocus(scrollback)}
1146+
willLoseFocus={() => this.doFocus(scrollback, idx)}
11281147
willFocusBlock={willFocusBlock}
11291148
isExperimental={hasCommand(_) && _.isExperimental}
11301149
isFocused={isFocused}

plugins/plugin-core-support/src/test/core-support/replay.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,16 +221,17 @@ Common.proxyDescribe(`core snapshot and replay by query ${process.env.MOCHA_RUN_
221221
.then(ReplExpect.okWithString(base64Output))
222222
.catch(Common.oops(this, true)))
223223

224+
const title = 'replay-by-query'
225+
224226
it('should snapshot', () =>
225-
CLI.command('snapshot /tmp/test.kui', this.app)
227+
CLI.command(`snapshot /tmp/test.kui --title ${title}`, this.app)
226228
.then(ReplExpect.justOK)
227229
.catch(Common.oops(this, true)))
228230

229-
it('should refresh', () => Common.refresh(this))
230-
231231
it('should replay by query', async () => {
232232
try {
233233
await this.app.client.url(`${process.env.WEBPACK_CLIENT_URL}?command=replay /tmp/test.kui`)
234+
await this.app.client.waitForExist(Selectors.TOP_TAB_WITH_TITLE(title), CLI.waitTimeout)
234235

235236
// verify the base64 command replay
236237
let idx = 0

plugins/plugin-core-support/src/test/core-support2/tab-navigation.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,4 @@ describe('tab navigation', function(this: Common.ISuite) {
154154
testSelector('#help-button', true, undefined, true)
155155
it('should have a new About Kui top tab', () =>
156156
this.app.client.waitForVisible(Selectors.TOP_TAB_WITH_TITLE('Welcome to Kui'), 5000))
157-
testPromptIsSelected()
158-
159-
// now the sidecar is open, so cycle through the sidecar tabs
160-
// testAboutMode('about', false, true)
161-
// testAboutMode('version', true) // hit enter on the Version tab
162157
})

0 commit comments

Comments
 (0)