Skip to content

Commit 7e84b20

Browse files
Mint de Witrjmunro
authored andcommitted
feat: edit mode for drag operations
1 parent aa484c6 commit 7e84b20

File tree

11 files changed

+127
-24
lines changed

11 files changed

+127
-24
lines changed

packages/blueprints-integration/src/ingest.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ export type DefaultUserOperations =
179179
| DefaultUserOperationRevertPart
180180
| DefaultUserOperationEditProperties
181181
| DefaultUserOperationImportMOSItem
182+
| DefaultUserOperationRetimePiece
182183

183184
export interface UserOperationChange<TCustomBlueprintOperations extends { id: string } = never> {
184185
/** Indicate that this change is from user operations */

packages/blueprints-integration/src/triggers.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,12 @@ export interface IShelfAction extends ITriggeredActionBase {
272272
filterChain: IGUIContextFilterLink[]
273273
}
274274

275+
export interface IEditModeAction extends ITriggeredActionBase {
276+
action: ClientActions.editMode
277+
state: true | false | 'toggle'
278+
filterChain: IGUIContextFilterLink[]
279+
}
280+
275281
export interface IGoToOnAirLineAction extends ITriggeredActionBase {
276282
action: ClientActions.goToOnAirLine
277283
filterChain: IGUIContextFilterLink[]
@@ -325,6 +331,7 @@ export type SomeAction =
325331
| IRundownPlaylistResetAction
326332
| IRundownPlaylistResyncAction
327333
| IShelfAction
334+
| IEditModeAction
328335
| IGoToOnAirLineAction
329336
| IRewindSegmentsAction
330337
| IShowEntireCurrentSegmentAction

packages/meteor-lib/src/triggers/RundownViewEventBus.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export enum RundownViewEvents {
2929
REVEAL_IN_SHELF = 'revealInShelf',
3030
SWITCH_SHELF_TAB = 'switchShelfTab',
3131
SHELF_STATE = 'shelfState',
32+
EDIT_MODE = 'editMode',
3233
MINI_SHELF_QUEUE_ADLIB = 'miniShelfQueueAdLib',
3334
GO_TO_PART = 'goToPart',
3435
GO_TO_PART_INSTANCE = 'goToPartInstance',
@@ -74,6 +75,10 @@ export interface ShelfStateEvent extends IEventContext {
7475
state: boolean | 'toggle'
7576
}
7677

78+
export interface EditModeEvent extends IEventContext {
79+
state: boolean | 'toggle'
80+
}
81+
7782
export interface MiniShelfQueueAdLibEvent extends IEventContext {
7883
forward: boolean
7984
}
@@ -139,6 +144,7 @@ export interface RundownViewEventBusEvents {
139144
[RundownViewEvents.SEGMENT_ZOOM_ON]: []
140145
[RundownViewEvents.SEGMENT_ZOOM_OFF]: []
141146
[RundownViewEvents.SHELF_STATE]: [e: ShelfStateEvent]
147+
[RundownViewEvents.EDIT_MODE]: [e: EditModeEvent]
142148
[RundownViewEvents.REVEAL_IN_SHELF]: [e: RevealInShelfEvent]
143149
[RundownViewEvents.SWITCH_SHELF_TAB]: [e: SwitchToShelfTabEvent]
144150
[RundownViewEvents.MINI_SHELF_QUEUE_ADLIB]: [e: MiniShelfQueueAdLibEvent]

packages/meteor-lib/src/triggers/actionFactory.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,17 @@ function createShelfAction(_filterChain: IGUIContextFilterLink[], state: boolean
286286
}
287287
}
288288

289+
function createEditModeAction(_filterChain: IGUIContextFilterLink[], state: boolean | 'toggle'): ExecutableAction {
290+
return {
291+
action: ClientActions.editMode,
292+
execute: () => {
293+
RundownViewEventBus.emit(RundownViewEvents.EDIT_MODE, {
294+
state,
295+
})
296+
},
297+
}
298+
}
299+
289300
function createMiniShelfQueueAdLibAction(_filterChain: IGUIContextFilterLink[], forward: boolean): ExecutableAction {
290301
return {
291302
action: ClientActions.miniShelfQueueAdLib,
@@ -442,6 +453,8 @@ export function createAction(
442453
switch (action.action) {
443454
case ClientActions.shelf:
444455
return createShelfAction(action.filterChain, action.state)
456+
case ClientActions.editMode:
457+
return createEditModeAction(action.filterChain, action.state)
445458
case ClientActions.goToOnAirLine:
446459
return createGoToOnAirLineAction(action.filterChain)
447460
case ClientActions.rewindSegments:

packages/shared-lib/src/core/model/ShowStyle.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ export enum ClientActions {
107107
'rewindSegments' = 'rewindSegments',
108108
'showEntireCurrentSegment' = 'showEntireCurrentSegment',
109109
'miniShelfQueueAdLib' = 'miniShelfQueueAdLib',
110+
'editMode' = 'editMode',
110111
}
111112

112113
export enum DeviceActions {

packages/webui/src/client/lib/ui/pieceUiClassNames.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ export function pieceUiClassNames(
1919
uiState?: {
2020
leftAnchoredWidth: number
2121
rightAnchoredWidth: number
22-
}
22+
},
23+
draggable?: boolean
2324
): string {
2425
const typeClass = layerType ? RundownUtils.getSourceLayerClassName(layerType) : ''
2526

@@ -57,5 +58,7 @@ export function pieceUiClassNames(
5758
'invert-flash': highlight,
5859

5960
'element-selected': selected,
61+
62+
'draggable-element': draggable,
6063
})
6164
}

packages/webui/src/client/styles/elementSelected.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ $glow-color: rgba(255, 255, 255, 0.58);
1818
}
1919
}
2020
}
21+
22+
.draggable-element {
23+
border: dotted white 1px;
24+
}

packages/webui/src/client/ui/RundownView/DragContext.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ export interface IDragContext {
2626
*/
2727
setHoveredPart: (partId: PartInstanceId, segmentId: SegmentId, position: { x: number; y: number }) => void
2828

29+
/**
30+
* Whether dragging is enabled
31+
*/
32+
enabled: boolean
33+
2934
/**
3035
* PieceId of the piece that is being dragged
3136
*/

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

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import { PartInstanceId, PieceInstanceId, SegmentId } from '@sofie-automation/corelib/dist/dataModel/Ids'
2-
import { PropsWithChildren, useRef, useState } from 'react'
3-
import { dragContext, IDragContext } from './DragContext'
4-
import { PieceUi } from '../SegmentContainer/withResolvedSegment'
5-
import { doUserAction, UserAction } from '../../lib/clientUserAction'
6-
import { MeteorCall } from '../../lib/meteorApi'
2+
import { PropsWithChildren, useCallback, useEffect, useRef, useState } from 'react'
3+
import { dragContext, IDragContext } from './DragContext.js'
4+
import { PieceUi } from '../SegmentContainer/withResolvedSegment.js'
5+
import { doUserAction, UserAction } from '../../lib/clientUserAction.js'
6+
import { MeteorCall } from '../../lib/meteorApi.js'
77
import { TFunction } from 'i18next'
88
import { UIParts } from '../Collections.js'
99
import { Segments } from '../../collections/index.js'
1010
import { literal } from '../../lib/tempLib.js'
1111
import { DefaultUserOperationRetimePiece, DefaultUserOperationsTypes } from '@sofie-automation/blueprints-integration'
12+
import RundownViewEventBus, {
13+
RundownViewEvents,
14+
EditModeEvent,
15+
} from '@sofie-automation/meteor-lib/dist/triggers/RundownViewEventBus'
1216

1317
const DRAG_TIMEOUT = 10000
1418

@@ -21,6 +25,8 @@ export function DragContextProvider({ t, children }: PropsWithChildren<Props>):
2125
const [pieceId, setPieceId] = useState<undefined | PieceInstanceId>(undefined)
2226
const [piece, setPiece] = useState<undefined | PieceUi>(undefined)
2327

28+
const [enabled, setEnabled] = useState(false)
29+
2430
const partIdRef = useRef<undefined | PartInstanceId>(undefined)
2531
const positionRef = useRef({ x: 0, y: 0 })
2632
const segmentIdRef = useRef<undefined | SegmentId>(undefined)
@@ -137,10 +143,27 @@ export function DragContextProvider({ t, children }: PropsWithChildren<Props>):
137143
positionRef.current = pos
138144
}
139145

146+
const onSetEditMode = useCallback((e: EditModeEvent) => {
147+
if (e.state === 'toggle') {
148+
setEnabled((s) => !s)
149+
} else {
150+
setEnabled(e.state)
151+
}
152+
}, [])
153+
154+
useEffect(() => {
155+
RundownViewEventBus.on(RundownViewEvents.EDIT_MODE, onSetEditMode)
156+
return () => {
157+
RundownViewEventBus.off(RundownViewEvents.EDIT_MODE, onSetEditMode)
158+
}
159+
})
160+
140161
const ctx = literal<IDragContext>({
141162
pieceId,
142163
piece,
143164

165+
enabled,
166+
144167
startDrag,
145168
setHoveredPart,
146169
})

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

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ export const SourceLayerItem = (props: Readonly<ISourceLayerItemProps>): JSX.Ele
122122
const [rightAnchoredWidth, setRightAnchoredWidth] = useState<number>(0)
123123

124124
const dragCtx = useContext(dragContext)
125+
const hasDraggableElement = !!piece.instance.piece.userEditOperations?.find(
126+
(op) => op.type === UserEditingType.SOFIE && op.id === DefaultUserOperationsTypes.RETIME_PIECE
127+
)
125128

126129
const state = {
127130
highlight,
@@ -193,25 +196,11 @@ export const SourceLayerItem = (props: Readonly<ISourceLayerItemProps>): JSX.Ele
193196
(e: React.MouseEvent<HTMLDivElement>) => {
194197
e.preventDefault()
195198
e.stopPropagation()
196-
console.log(
197-
'mousedown',
198-
UserEditingType.SOFIE,
199-
DefaultUserOperationsTypes,
200-
piece.instance.piece.userEditOperations?.map(
201-
(op) => op.type === UserEditingType.SOFIE && op.id === '__sofie-retime-piece'
202-
)
203-
)
204199

205-
if (
206-
!piece.instance.piece.userEditOperations?.find(
207-
// (op) => op.type === UserEditingType.SOFIE && op.id === DefaultUserOperationsTypes.RETIME_PIECE
208-
(op) => op.type === UserEditingType.SOFIE && op.id === '__sofie-retime-piece'
209-
)
210-
)
211-
return
200+
if (!hasDraggableElement) return
212201

213202
const targetPos = (e.target as HTMLDivElement).getBoundingClientRect()
214-
if (dragCtx)
203+
if (dragCtx && dragCtx.enabled)
215204
dragCtx.startDrag(
216205
piece,
217206
timeScale,
@@ -223,7 +212,7 @@ export const SourceLayerItem = (props: Readonly<ISourceLayerItemProps>): JSX.Ele
223212
part.instance.segmentId
224213
)
225214
},
226-
[piece, timeScale]
215+
[piece, timeScale, dragCtx]
227216
)
228217
const itemMouseUp = useCallback((e: any) => {
229218
const eM = e as MouseEvent
@@ -614,8 +603,10 @@ export const SourceLayerItem = (props: Readonly<ISourceLayerItemProps>): JSX.Ele
614603
layer.type,
615604
part.partId,
616605
highlight,
617-
elementWidth
606+
elementWidth,
618607
// this.state
608+
undefined,
609+
hasDraggableElement && dragCtx?.enabled
619610
)}
620611
data-obj-id={piece.instance._id}
621612
ref={setRef}

0 commit comments

Comments
 (0)