Skip to content

Commit 3aaea87

Browse files
committed
feat: select/deselect an element - fix flickering upen commit changes
1 parent 8220392 commit 3aaea87

File tree

4 files changed

+44
-34
lines changed

4 files changed

+44
-34
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ interface IProps {
102102
showDurationSourceLayers?: Set<ISourceLayer['_id']>
103103
fixedSegmentDuration: boolean | undefined
104104
onSegmentSelect: (segmentId: SegmentId) => void
105+
clearSelections: () => void
105106
isSelected: boolean
106107
}
107108
interface IStateHeader {
@@ -1063,7 +1064,11 @@ export class SegmentTimelineClass extends React.Component<Translated<WithTiming<
10631064
<div
10641065
onDoubleClick={() => {
10651066
if (this.props.studio.settings.enableUserEdits && this.props.onSegmentSelect) {
1066-
this.props.onSegmentSelect(this.props.segment._id)
1067+
if (!this.props.isSelected) {
1068+
this.props.onSegmentSelect(this.props.segment._id)
1069+
} else {
1070+
this.props.clearSelections()
1071+
}
10671072
}
10681073
}}
10691074
>

packages/webui/src/client/ui/SegmentTimeline/SegmentTimelineContainer.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ interface IState {
7272

7373
interface IProps extends IResolvedSegmentProps {
7474
id: string
75-
onSegmentSelect: (segmentId: SegmentId) => void
7675
}
7776

7877
export function SegmentTimelineContainer(props: Readonly<IProps>): JSX.Element {
@@ -142,7 +141,7 @@ export function SegmentTimelineContainer(props: Readonly<IProps>): JSX.Element {
142141
}
143142

144143
function SegmentTimelineContainerWithSelection(props: Readonly<IProps>): JSX.Element {
145-
const { clearAndSetSelection, isSelected } = useSelection()
144+
const { clearAndSetSelection, isSelected, clearSelections } = useSelection()
146145

147146
const handleSegmentSelect = (segmentId: SegmentId) => {
148147
console.log('handleSegmentSelect', segmentId)
@@ -161,12 +160,15 @@ function SegmentTimelineContainerWithSelection(props: Readonly<IProps>): JSX.Ele
161160
{...props}
162161
isSelected={isElementSelected()}
163162
onSegmentSelect={handleSegmentSelect}
163+
clearSelections={clearSelections}
164164
/>
165165
)
166166
}
167167

168168
interface IWithSelectionProps extends IProps {
169169
isSelected: boolean
170+
onSegmentSelect: (segmentId: SegmentId) => void
171+
clearSelections: () => void
170172
}
171173

172174
const SegmentTimelineContainerContent = withResolvedSegment(
@@ -732,6 +734,7 @@ const SegmentTimelineContainerContent = withResolvedSegment(
732734
fixedSegmentDuration={this.props.fixedSegmentDuration}
733735
showDurationSourceLayers={this.props.showDurationSourceLayers}
734736
onSegmentSelect={this.handleSegmentSelect}
737+
clearSelections={this.props.clearSelections}
735738
isSelected={this.props.isSelected}
736739
/>
737740
)}

packages/webui/src/client/ui/SegmentTimeline/SourceLayerItem.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ const SourceLayerItemWithSelection = withTranslation()(
730730
)
731731

732732
export const SourceLayerItem = (props: ISourceLayerItemProps): React.ReactElement => {
733-
const { isSelected, clearAndSetSelection } = useSelection()
733+
const { isSelected, clearAndSetSelection, clearSelections } = useSelection()
734734

735735
const isPieceSelected = isSelected(props.piece.instance.piece._id)
736736

@@ -740,7 +740,11 @@ export const SourceLayerItem = (props: ISourceLayerItemProps): React.ReactElemen
740740
// As the piece currently doesn't have a unique ID, that can be used for back reference
741741
// If it's not an instance
742742
const partId = props.part.instance.part._id
743-
clearAndSetSelection({ type: 'part', elementId: partId })
743+
if (!isPieceSelected) {
744+
clearAndSetSelection({ type: 'part', elementId: partId })
745+
} else {
746+
clearSelections()
747+
}
744748
props.onClick?.(piece, e)
745749
},
746750
[isPieceSelected]

packages/webui/src/client/ui/UserEditOperations/PropertiesPanel.tsx

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ export function PropertiesPanel(): JSX.Element {
3636
const { listSelectedElements } = useSelection()
3737
const selectedElement = listSelectedElements()?.[0]
3838
const { t } = useTranslation()
39-
if (!selectedElement) return <></>
4039

4140
const [pendingChanges, setPendingChanges] = React.useState<PendingChange[]>([])
4241
const hasPendingChanges = pendingChanges.length > 0
@@ -52,20 +51,18 @@ export function PropertiesPanel(): JSX.Element {
5251
}, [])
5352

5453
const part = useTracker(() => {
55-
const foundPart = UIParts.findOne({ _id: selectedElement.elementId })
5654
setPendingChanges([])
57-
return foundPart
58-
}, [selectedElement.elementId])
55+
return UIParts.findOne({ _id: selectedElement?.elementId })
56+
}, [selectedElement?.elementId])
5957

6058
const segment: DBSegment | undefined = useTracker(
61-
() => Segments.findOne({ _id: part ? part.segmentId : selectedElement.elementId }),
62-
[selectedElement.elementId]
59+
() => Segments.findOne({ _id: part ? part.segmentId : selectedElement?.elementId }),
60+
[selectedElement?.elementId]
6361
)
6462
const rundownId = part ? part.rundownId : segment?.rundownId
6563

66-
if (!rundownId) return <></>
67-
6864
const handleCommitChanges = async (e: React.MouseEvent) => {
65+
if (!rundownId || !selectedElement) return
6966
for (const change of pendingChanges) {
7067
doUserAction(t, e, UserAction.EXECUTE_USER_OPERATION, (e, ts) =>
7168
MeteorCall.userAction.executeUserChangeOperation(
@@ -84,35 +81,36 @@ export function PropertiesPanel(): JSX.Element {
8481
)
8582
)
8683
}
87-
setPendingChanges([])
84+
// Delay the Clear pending changes after executing to avoid async flickering:
85+
setTimeout(() => setPendingChanges([]), 100)
8886
}
8987

9088
const handleRevertChanges = (e: React.MouseEvent) => {
89+
if (!rundownId || !selectedElement) return
9190
setPendingChanges([])
92-
rundownId &&
93-
doUserAction(t, e, UserAction.EXECUTE_USER_OPERATION, (e, ts) =>
94-
MeteorCall.userAction.executeUserChangeOperation(
95-
e,
96-
ts,
97-
rundownId,
98-
{
99-
segmentExternalId: segment?.externalId,
100-
partExternalId: part?.externalId,
101-
pieceExternalId: undefined,
102-
},
103-
{
104-
id:
105-
selectedElement.type === 'partInstance'
106-
? DefaultUserOperationsTypes.REVERT_PART
107-
: DefaultUserOperationsTypes.REVERT_SEGMENT,
108-
}
109-
)
91+
doUserAction(t, e, UserAction.EXECUTE_USER_OPERATION, (e, ts) =>
92+
MeteorCall.userAction.executeUserChangeOperation(
93+
e,
94+
ts,
95+
rundownId,
96+
{
97+
segmentExternalId: segment?.externalId,
98+
partExternalId: part?.externalId,
99+
pieceExternalId: undefined,
100+
},
101+
{
102+
id:
103+
selectedElement.type === 'partInstance'
104+
? DefaultUserOperationsTypes.REVERT_PART
105+
: DefaultUserOperationsTypes.REVERT_SEGMENT,
106+
}
110107
)
108+
)
111109
}
112110

113111
return (
114112
<div className="propertiespanel-pop-up">
115-
{selectedElement.type === 'part' && (
113+
{rundownId && selectedElement?.type === 'part' && (
116114
<>
117115
<div className="propertiespanel-pop-up__header">
118116
{part?.userEditOperations &&
@@ -168,7 +166,7 @@ export function PropertiesPanel(): JSX.Element {
168166
</div>
169167
</>
170168
)}
171-
{selectedElement.type === 'segment' && (
169+
{rundownId && selectedElement?.type === 'segment' && (
172170
<>
173171
<div className="propertiespanel-pop-up__header">
174172
{segment?.userEditOperations &&

0 commit comments

Comments
 (0)