Skip to content

Commit da8a216

Browse files
committed
fix(webui): More fixes [copilot]
1 parent d8b992f commit da8a216

18 files changed

Lines changed: 135 additions & 22 deletions

File tree

packages/webui/src/client/lib/VirtualElement.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,12 @@ export class ElementObserverManager {
450450
callback()
451451
}
452452
})
453+
454+
// Ensure detached entries are aggressively cleaned even without follow-up DOM mutations.
455+
this.pruneDetachedObservedElements()
456+
if (this.observedElements.size === 0) {
457+
this.disconnectMutationObserver()
458+
}
453459
})
454460

455461
// Configure MutationObserver once and only connect/disconnect based on active observed elements.

packages/webui/src/client/lib/viewPort.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ export function resetViewportScrollState(): void {
113113
viewPortScrollingState.isProgrammaticScrollInProgress = false
114114
}
115115

116+
export function clearViewportLifecycleState(): void {
117+
resetViewportScrollState()
118+
viewPortScrollingState.lastProgrammaticScrollTime = 0
119+
focusState.isScrolling = false
120+
focusState.startTime = 0
121+
}
122+
116123
export async function scrollToPartInstance(
117124
partInstanceId: PartInstanceId,
118125
forceScroll?: boolean,

packages/webui/src/client/ui/PreviewPopUp/PreviewPopUpContext.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ interface PreviewSession {
389389
export function PreviewPopUpContextProvider({ children }: React.PropsWithChildren<{}>): React.ReactNode {
390390
const currentHandle = useRef<IPreviewPopUpSession>()
391391
const previewRef = useRef<PreviewPopUpHandle>(null)
392+
const closeSessionRef = useRef<() => void>(() => undefined)
392393

393394
const [previewSession, setPreviewSession] = useState<PreviewSession | null>(null)
394395
const [previewContent, setPreviewContent] = useState<PreviewContentUI[] | null>(null)
@@ -411,12 +412,39 @@ export function PreviewPopUpContextProvider({ children }: React.PropsWithChildre
411412
setTime(null)
412413
}, [])
413414

415+
useEffect(() => {
416+
closeSessionRef.current = closeSession
417+
}, [closeSession])
418+
414419
useEffect(() => {
415420
return () => {
416421
closeSession()
417422
}
418423
}, [closeSession])
419424

425+
useEffect(() => {
426+
if (!previewSession) return
427+
const anchor = previewSession.anchor
428+
if (!(anchor instanceof HTMLElement)) return
429+
430+
let rafHandle: number | undefined
431+
const checkAnchorConnection = () => {
432+
if (!anchor.isConnected) {
433+
closeSessionRef.current()
434+
return
435+
}
436+
rafHandle = window.requestAnimationFrame(checkAnchorConnection)
437+
}
438+
439+
rafHandle = window.requestAnimationFrame(checkAnchorConnection)
440+
441+
return () => {
442+
if (rafHandle !== undefined) {
443+
window.cancelAnimationFrame(rafHandle)
444+
}
445+
}
446+
}, [previewSession])
447+
420448
const context: IPreviewPopUpContext = {
421449
requestPreview: (anchor, content, opts) => {
422450
if (isDetachedHTMLElement(anchor)) {

packages/webui/src/client/ui/RundownView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
maintainFocusOnPartInstance,
3131
scrollToPartInstance,
3232
getHeaderHeight,
33-
resetViewportScrollState,
33+
clearViewportLifecycleState,
3434
} from '../lib/viewPort.js'
3535
import { AfterBroadcastForm } from './AfterBroadcastForm.js'
3636
import { RundownRightHandControls } from './RundownView/RundownRightHandControls.js'
@@ -615,7 +615,7 @@ const RundownViewContent = translateWithTracker<IPropsWithReady & ITrackedProps,
615615
document.documentElement.removeAttribute('data-bs-theme')
616616
window.removeEventListener('beforeunload', this.onBeforeUnload)
617617
this.clearPendingDeferredCallbacks()
618-
resetViewportScrollState()
618+
clearViewportLifecycleState()
619619

620620
documentTitle.set(null)
621621

packages/webui/src/client/ui/SegmentList/LinePartMainPiece/LinePartMainPiece.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,13 @@ export function LinePartMainPiece({
144144
}
145145
setHover(true)
146146

147+
if (previewSession.current) {
148+
previewSession.current.close()
149+
previewSession.current = null
150+
}
151+
147152
if (previewContents.length > 0)
148-
previewSession.current = previewContext.requestPreview(e.target as any, previewContents, {
153+
previewSession.current = previewContext.requestPreview(e.currentTarget, previewContents, {
149154
...previewOptions,
150155
time: mousePosition * (piece.instance.piece.content.sourceDuration || 0),
151156
initialOffsetX: e.screenX,

packages/webui/src/client/ui/SegmentList/LinePartPieceIndicator/LinePartScriptPiece.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,13 @@ export function LinePartScriptPiece({ pieces }: IProps): JSX.Element {
3737

3838
function onMouseEnter(e: React.PointerEvent<HTMLDivElement>) {
3939
// setHover(true)
40+
if (previewSession.current) {
41+
previewSession.current.close()
42+
previewSession.current = null
43+
}
44+
4045
if (previewProps?.contents && previewProps.contents.length > 0)
41-
previewSession.current = previewContext.requestPreview(e.target as any, previewProps.contents, {
46+
previewSession.current = previewContext.requestPreview(e.currentTarget, previewProps.contents, {
4247
...previewProps.options,
4348
initialOffsetX: e.screenX,
4449
})

packages/webui/src/client/ui/SegmentList/LinePartSecondaryPiece/LinePartSecondaryPiece.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,13 @@ export const LinePartSecondaryPiece: React.FC<IProps> = React.memo(function Line
5757
return
5858
}
5959

60+
if (previewSession.current) {
61+
previewSession.current.close()
62+
previewSession.current = null
63+
}
64+
6065
if (previewProps.contents.length > 0)
61-
previewSession.current = previewContext.requestPreview(e.target as any, previewProps.contents, {
66+
previewSession.current = previewContext.requestPreview(e.currentTarget, previewProps.contents, {
6267
...previewProps.options,
6368
initialOffsetX: e.screenX,
6469
})

packages/webui/src/client/ui/SegmentStoryboard/StoryboardPartSecondaryPieces/StoryboardSecondaryPiece.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,13 @@ export function StoryboardSecondaryPiece(props: IProps): JSX.Element {
120120
width,
121121
})
122122

123+
if (previewSession.current) {
124+
previewSession.current.close()
125+
previewSession.current = null
126+
}
127+
123128
if (previewContents.length > 0)
124-
previewSession.current = previewContext.requestPreview(e.target as any, previewContents, {
129+
previewSession.current = previewContext.requestPreview(e.currentTarget, previewContents, {
125130
...previewOptions,
126131
initialOffsetX: e.screenX,
127132
})

packages/webui/src/client/ui/SegmentStoryboard/StoryboardPartThumbnail/StoryboardPartThumbnailInner.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ export function StoryboardPartThumbnailInner({
6262
}
6363
setHover(true)
6464

65+
if (previewSession.current) {
66+
previewSession.current.close()
67+
previewSession.current = null
68+
}
69+
6570
const newOffset = thumbnailEl.current && getElementDocumentOffset(thumbnailEl.current)
6671
if (newOffset !== null) {
6772
setOrigin(newOffset)
@@ -76,7 +81,7 @@ export function StoryboardPartThumbnailInner({
7681
}
7782

7883
if (previewContents.length > 0)
79-
previewSession.current = previewContext.requestPreview(e.target as any, previewContents, {
84+
previewSession.current = previewContext.requestPreview(e.currentTarget, previewContents, {
8085
...previewOptions,
8186
time: mousePosition * (piece.instance.piece.content.sourceDuration || 0),
8287
initialOffsetX: e.screenX,

packages/webui/src/client/ui/SegmentTimeline/Parts/InvalidPartCover.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,13 @@ export function InvalidPartCover({ className, invalidReason }: Readonly<IProps>)
2222
return
2323
}
2424

25+
if (previewSession.current) {
26+
previewSession.current.close()
27+
previewSession.current = null
28+
}
29+
2530
if (invalidReason?.message && !previewSession.current) {
26-
previewSession.current = previewContext.requestPreview(e.target as HTMLDivElement, [
31+
previewSession.current = previewContext.requestPreview(e.currentTarget, [
2732
{
2833
type: 'warning',
2934
content: invalidReason.message,

0 commit comments

Comments
 (0)