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

Commit 3405b37

Browse files
committed
fix(packages/core): drilldown versus back button race condition
Fixes #3114
1 parent 197efa8 commit 3405b37

File tree

2 files changed

+57
-27
lines changed

2 files changed

+57
-27
lines changed

packages/core/src/models/tab-state.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ export default class TabState {
4646

4747
private _currentBottomInputValue = ''
4848

49+
/** is there a drilldown in progress for this tab? */
50+
public drilldownInProgress: Promise<void>
51+
4952
public get env() {
5053
return this._env
5154
}

packages/core/src/webapp/picture-in-picture.ts

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,12 @@ const restore = (
104104
// sidecar.classList.add('custom-content')
105105
// pippedContainer.classList.remove('picture-in-picture-stage1')
106106
if (pippedContainer !== true && pippedContainer !== false) {
107-
if (pippedContainer.parentNode) pippedContainer.parentNode.removeChild(pippedContainer)
108-
parent.appendChild(pippedContainer)
107+
if (!pippedContainer.classList.contains('sidecar-content')) {
108+
if (pippedContainer.parentNode) {
109+
pippedContainer.parentNode.removeChild(pippedContainer)
110+
}
111+
parent.appendChild(pippedContainer)
112+
}
109113
}
110114
// pippedContainer.onclick = null
111115
// }, 300)
@@ -128,7 +132,9 @@ const pip = (
128132
) => {
129133
try {
130134
if (container !== true && container !== false) {
131-
container.parentNode.removeChild(container)
135+
if (!container.classList.contains('sidecar-content')) {
136+
container.parentNode.removeChild(container)
137+
}
132138
}
133139
} catch (e) {
134140
// ok
@@ -156,7 +162,11 @@ const pip = (
156162

157163
backButton.addEventListener(
158164
'click',
159-
() => {
165+
async () => {
166+
// Notes: wait for any drilldown in the current tab to finish
167+
// before actuating the back button behavior.
168+
// https://github.com/IBM/kui/issues/3114
169+
await (tab.state.drilldownInProgress || Promise.resolve())
160170
restoreFn()
161171
backContainer.classList.remove('has-back-button')
162172
},
@@ -242,7 +252,7 @@ export const drilldown = (
242252
ccontainer?: string | Element,
243253
returnTo?: string,
244254
options?: PipOptions
245-
) => (event?: Event) => {
255+
) => async (event?: Event): Promise<void> => {
246256
if (event) event.stopPropagation()
247257

248258
// maybe ccontainer is a query selector
@@ -288,30 +298,47 @@ export const drilldown = (
288298
// now we can safely begin executing the command
289299
debug('executing command', command)
290300

291-
if (typeof command === 'string') {
292-
debug('drilling down with string command')
293-
294-
const execOptions: ExecOptions = Object.assign(
295-
{},
296-
{
297-
isDrilldown: true,
298-
preserveBackButton: true,
299-
rethrowErrors: true,
300-
reportErrors: true
301-
},
302-
(options && options.execOptions) || {}
303-
)
304-
305-
if (!options || options.exec === 'pexec') {
306-
return pexec(command, execOptions).catch(restoreFn)
301+
// eslint-disable-next-line no-async-promise-executor
302+
tab.state.drilldownInProgress = new Promise(async resolve => {
303+
const done = () => {
304+
tab.state.drilldownInProgress = undefined
305+
resolve()
306+
}
307+
308+
if (typeof command === 'string') {
309+
debug('drilling down with string command')
310+
311+
const execOptions: ExecOptions = Object.assign(
312+
{},
313+
{
314+
isDrilldown: true,
315+
preserveBackButton: true,
316+
rethrowErrors: true,
317+
reportErrors: true
318+
},
319+
(options && options.execOptions) || {}
320+
)
321+
322+
if (!options || options.exec === 'pexec') {
323+
return pexec(command, execOptions)
324+
.then(done)
325+
.catch(restoreFn)
326+
} else {
327+
return qexec(command, undefined, undefined, execOptions)
328+
.then(done)
329+
.catch(restoreFn)
330+
}
331+
} else if (typeof command === 'function') {
332+
return command()
333+
.then(done)
334+
.catch(restoreFn)
307335
} else {
308-
return qexec(command, undefined, undefined, execOptions).catch(restoreFn)
336+
await showEntity(tab, command, { preserveBackButton: true })
337+
done()
309338
}
310-
} else if (typeof command === 'function') {
311-
return command().catch(restoreFn)
312-
} else {
313-
return showEntity(tab, command, { preserveBackButton: true })
314-
}
339+
})
340+
341+
await tab.state.drilldownInProgress
315342
}
316343

317344
export default drilldown

0 commit comments

Comments
 (0)