Skip to content

Commit ec7665f

Browse files
Merge pull request #1727 from bbc/fix/SOFIE-449-counter-touchups
Fix: SOFIE-449 counter touchups
2 parents cc64fc0 + 8499b3b commit ec7665f

17 files changed

Lines changed: 215 additions & 166 deletions

packages/corelib/src/playout/rundownTiming.ts

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export namespace PlaylistTiming {
5454
}
5555
}
5656

57-
export function getExpectedEnd(timing: RundownPlaylistTiming, startedPlayback?: number): number | undefined {
57+
export function getExpectedEnd(timing: RundownPlaylistTiming): number | undefined {
5858
if (PlaylistTiming.isPlaylistTimingBackTime(timing)) {
5959
return timing.expectedEnd
6060
} else if (PlaylistTiming.isPlaylistTimingForwardTime(timing)) {
@@ -63,26 +63,16 @@ export namespace PlaylistTiming {
6363
(timing.expectedDuration ? timing.expectedStart + timing.expectedDuration : undefined)
6464
)
6565
} else if (PlaylistTiming.isPlaylistDurationTimed(timing)) {
66-
if (!startedPlayback) {
67-
// before the show, estimate the end from start + dur
68-
return timing.expectedStart ? timing.expectedStart + timing.expectedDuration : undefined
69-
} else {
70-
// after starting the show, project the end from startedPlayback + dur
71-
return startedPlayback + timing.expectedDuration
72-
}
66+
return timing.expectedStart && timing.expectedDuration
67+
? timing.expectedStart + timing.expectedDuration
68+
: undefined
7369
} else {
7470
return undefined
7571
}
7672
}
7773

7874
export function getExpectedDuration(timing: RundownPlaylistTiming): number | undefined {
79-
if (PlaylistTiming.isPlaylistTimingForwardTime(timing)) {
80-
return timing.expectedDuration
81-
} else if (PlaylistTiming.isPlaylistTimingBackTime(timing)) {
82-
return timing.expectedDuration
83-
} else {
84-
return undefined
85-
}
75+
return timing.expectedDuration
8676
}
8777

8878
export function getEstimatedEnd(
@@ -91,6 +81,14 @@ export namespace PlaylistTiming {
9181
remainingPlaylistDuration?: number,
9282
startedPlayback?: number
9383
): number | undefined {
84+
if (PlaylistTiming.isPlaylistDurationTimed(timing) && timing.expectedDuration) {
85+
if (startedPlayback) {
86+
return startedPlayback + timing.expectedDuration
87+
} else if (timing.expectedStart) {
88+
return timing.expectedStart + timing.expectedDuration
89+
}
90+
}
91+
9492
if (remainingPlaylistDuration !== undefined) {
9593
const frontAnchor = startedPlayback ? now : Math.max(now, PlaylistTiming.getExpectedStart(timing) ?? now)
9694

@@ -99,6 +97,23 @@ export namespace PlaylistTiming {
9997
return undefined
10098
}
10199

100+
export function getRemainingDuration(
101+
timing: RundownPlaylistTiming,
102+
now: number,
103+
remainingPlaylistDuration?: number,
104+
startedPlayback?: number
105+
): number | undefined {
106+
if (PlaylistTiming.isPlaylistDurationTimed(timing) && timing.expectedDuration) {
107+
if (startedPlayback) {
108+
return startedPlayback + timing.expectedDuration - now
109+
} else {
110+
return timing.expectedDuration
111+
}
112+
}
113+
114+
return remainingPlaylistDuration
115+
}
116+
102117
export function sortTimings(
103118
a: ReadonlyDeep<{ timing: RundownPlaylistTiming }>,
104119
b: ReadonlyDeep<{ timing: RundownPlaylistTiming }>

packages/webui/src/client/lib/Components/CounterComponents.tsx

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import Moment from 'react-moment'
22
import { RundownUtils } from '../rundown.js'
33

4+
import { Countdown } from '../../ui/RundownView/RundownHeader/Countdown.js'
5+
46
interface OverUnderProps {
57
value: number
68
}
@@ -23,18 +25,24 @@ export const PlannedEndComponent = (props: OverUnderProps): JSX.Element => {
2325
)
2426
}
2527

26-
export const TimeToPlannedEndComponent = (props: OverUnderProps): JSX.Element => {
28+
export const TimeToFromPlannedEndComponent = (props: OverUnderProps): JSX.Element => {
29+
const isOver = props.value > -100
2730
return (
28-
<span className="counter-component__time-to-planned-end">
29-
{RundownUtils.formatDiffToTimecode(props.value, true, false, true, true, true, undefined, true, true)}
30-
</span>
31-
)
32-
}
33-
34-
export const TimeSincePlannedEndComponent = (props: OverUnderProps): JSX.Element => {
35-
return (
36-
<span className="counter-component__time-since-planned-end">
37-
{RundownUtils.formatDiffToTimecode(props.value, true, false, true, true, true, undefined, true, true)}
38-
</span>
31+
<Countdown
32+
className={isOver ? 'counter-component__time-since-planned-end' : 'counter-component__time-to-planned-end'}
33+
ms={props.value}
34+
>
35+
{`${isOver ? '+' : ''}${RundownUtils.formatDiffToTimecode(
36+
props.value, // restored to match Rem. Dur math (negative value triggers Math.ceil)
37+
false,
38+
false, // disable hardcoded showHours
39+
true,
40+
true,
41+
true, // useSmartHours automatically shows hours if > 0
42+
'',
43+
true,
44+
true
45+
)}`}
46+
</Countdown>
3947
)
4048
}

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

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ export class RundownPlaylistClientUtil {
9696
currentPartInstance: PartInstance | undefined
9797
nextPartInstance: PartInstance | undefined
9898
previousPartInstance: PartInstance | undefined
99-
partInstanceToCountTimeFrom: PartInstance | undefined
10099
} {
101100
let unorderedRundownIds = rundownIds0
102101
if (!unorderedRundownIds) {
@@ -117,26 +116,10 @@ export class RundownPlaylistClientUtil {
117116
}).fetch()
118117
: []
119118

120-
const areAllPartsTimed = !!UIPartInstances.findOne({
121-
rundownId: { $in: unorderedRundownIds },
122-
['part.untimed']: { $ne: true },
123-
})
124-
125-
const partInstanceToCountTimeFrom = UIPartInstances.findOne(
126-
{
127-
rundownId: { $in: unorderedRundownIds },
128-
reset: { $ne: true },
129-
takeCount: { $exists: true },
130-
['part.untimed']: { $ne: areAllPartsTimed },
131-
},
132-
{ sort: { takeCount: 1 } }
133-
)
134-
135119
return {
136120
currentPartInstance: instances.find((inst) => inst._id === playlist.currentPartInfo?.partInstanceId),
137121
nextPartInstance: instances.find((inst) => inst._id === playlist.nextPartInfo?.partInstanceId),
138122
previousPartInstance: instances.find((inst) => inst._id === playlist.previousPartInfo?.partInstanceId),
139-
partInstanceToCountTimeFrom,
140123
}
141124
}
142125

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,12 @@ export function getPlaylistTimingDiff(
858858
} else if (PlaylistTiming.isPlaylistDurationTimed(timing)) {
859859
const backAnchorTimeWithoutBreaks =
860860
timingContext.nextRundownAnchor ??
861-
PlaylistTiming.getExpectedEnd(timing, playlist.startedPlayback) ??
861+
PlaylistTiming.getEstimatedEnd(
862+
timing,
863+
currentTime,
864+
undefined,
865+
playlist.activationId ? playlist.startedPlayback : undefined
866+
) ??
862867
currentTime + timing.expectedDuration
863868
backAnchor = timingContext.nextRundownAnchor ?? backAnchorTimeWithoutBreaks
864869
frontAnchor = Math.max(currentTime, playlist.startedPlayback || PlaylistTiming.getExpectedStart(timing) || 0)

packages/webui/src/client/styles/countdown/director.scss

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,17 @@ $hold-status-color: $liveline-timecode-color;
4343
text-transform: uppercase;
4444

4545
.director-screen__top__spacer {
46-
flex-grow: 4;
46+
flex: 1 1 0;
4747
}
4848

4949
.director-screen__top__planned-end {
50-
flex-grow: 2;
50+
flex: 1 1 0;
5151
text-align: left;
52+
transform: translateY(0.35em);
53+
}
54+
55+
.director-screen__top__planned-container {
56+
flex: 1 1 0;
5257
}
5358

5459
.director-screen__top__center,

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

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,20 +92,35 @@
9292

9393
.counter-component__planned-end {
9494
color: #ffffff;
95-
letter-spacing: 0%;
9695
text-align: right;
96+
line-height: 1;
9797

98-
letter-spacing: 0.01em;
98+
letter-spacing: 0.02em;
9999
font-variation-settings:
100-
'slnt' -7,
101-
'wdth' 70,
102-
'wght' 500;
100+
'wdth' 85,
101+
'wght' 400,
102+
'slnt' -5,
103+
'GRAD' 0,
104+
'opsz' 40,
105+
'XOPQ' 96,
106+
'XTRA' 468,
107+
'YOPQ' 79,
108+
'YTAS' 750,
109+
'YTFI' 738,
110+
'YTLC' 548,
111+
'YTDE' -203,
112+
'YTUC' 712;
103113
}
104114

105115
.counter-component__time-to-planned-end {
106-
color: $general-countdown-to-next-color;
116+
color: #ffffff;
107117
letter-spacing: 0%;
108118

119+
&.countdown {
120+
justify-content: center;
121+
transition: none;
122+
}
123+
109124
letter-spacing: 0.01em;
110125
font-variation-settings:
111126
'GRAD' 0,
@@ -121,12 +136,21 @@
121136
'slnt' 0,
122137
'wdth' 70,
123138
'wght' 500;
139+
140+
.countdown__counter {
141+
color: inherit;
142+
margin-left: 0;
143+
}
124144
}
125145

126146
.counter-component__time-since-planned-end {
127147
color: $over-under-over-color;
128-
text-align: right;
129-
margin-left: 1.2vw;
148+
text-align: center;
149+
150+
&.countdown {
151+
justify-content: center;
152+
transition: none;
153+
}
130154

131155
letter-spacing: 0.01em;
132156
font-variation-settings:
@@ -143,4 +167,9 @@
143167
'slnt' 0,
144168
'wdth' 70,
145169
'wght' 600;
170+
171+
.countdown__counter {
172+
color: inherit;
173+
margin-left: 0;
174+
}
146175
}

packages/webui/src/client/ui/ClockView/DirectorScreen/DirectorScreen.tsx

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ export interface DirectorScreenTrackedProps {
141141
nextShowStyleBaseId: ShowStyleBaseId | undefined
142142
showStyleBaseIds: ShowStyleBaseId[]
143143
rundownIds: RundownId[]
144-
partInstanceToCountTimeFrom: PartInstance | undefined
145144
}
146145

147146
function getShowStyleBaseIdSegmentPartUi(
@@ -270,7 +269,6 @@ const getDirectorScreenReactive = (props: DirectorScreenProps): DirectorScreenTr
270269
let nextSegment: SegmentUi | undefined = undefined
271270
let nextPartInstanceUi: PartUi | undefined = undefined
272271
let nextShowStyleBaseId: ShowStyleBaseId | undefined = undefined
273-
let partInstanceToCountTimeFromUi: PartInstance | undefined = undefined
274272

275273
if (playlist) {
276274
rundowns = RundownPlaylistCollectionUtil.getRundownsOrdered(playlist)
@@ -283,10 +281,7 @@ const getDirectorScreenReactive = (props: DirectorScreenProps): DirectorScreenTr
283281
}
284282

285283
showStyleBaseIds = rundowns.map((rundown) => rundown.showStyleBaseId)
286-
const { currentPartInstance, nextPartInstance, partInstanceToCountTimeFrom } =
287-
RundownPlaylistClientUtil.getSelectedPartInstances(playlist)
288-
289-
partInstanceToCountTimeFromUi = partInstanceToCountTimeFrom
284+
const { currentPartInstance, nextPartInstance } = RundownPlaylistClientUtil.getSelectedPartInstances(playlist)
290285

291286
const partInstance = currentPartInstance ?? nextPartInstance
292287
if (partInstance) {
@@ -356,7 +351,6 @@ const getDirectorScreenReactive = (props: DirectorScreenProps): DirectorScreenTr
356351
nextSegment,
357352
nextPartInstance: nextPartInstanceUi,
358353
nextShowStyleBaseId,
359-
partInstanceToCountTimeFrom: partInstanceToCountTimeFromUi,
360354
}
361355
}
362356

@@ -380,6 +374,7 @@ function useDirectorScreenSubscriptions(props: DirectorScreenProps): void {
380374

381375
useSubscription(CorelibPubSub.segments, rundownIds, {})
382376
useSubscription(CorelibPubSub.parts, rundownIds, null)
377+
useSubscription(MeteorPubSub.uiParts, playlist?._id ?? null)
383378
useSubscription(MeteorPubSub.uiPartInstances, playlist?.activationId ?? null)
384379
useSubscriptions(
385380
MeteorPubSub.uiShowStyleBase,
@@ -388,11 +383,7 @@ function useDirectorScreenSubscriptions(props: DirectorScreenProps): void {
388383
useSubscription(CorelibPubSub.showStyleVariants, null, showStyleVariantIds)
389384
useSubscription(MeteorPubSub.rundownLayouts, showStyleBaseIds)
390385

391-
const {
392-
currentPartInstance,
393-
nextPartInstance,
394-
partInstanceToCountTimeFrom: firstTakenPartInstance,
395-
} = useTracker(
386+
const { currentPartInstance, nextPartInstance } = useTracker(
396387
() => {
397388
const playlist = RundownPlaylists.findOne(props.playlistId, {
398389
fields: {
@@ -410,7 +401,6 @@ function useDirectorScreenSubscriptions(props: DirectorScreenProps): void {
410401
currentPartInstance: undefined,
411402
nextPartInstance: undefined,
412403
previousPartInstance: undefined,
413-
partInstanceToCountTimeFrom: undefined,
414404
}
415405
}
416406
},
@@ -419,14 +409,12 @@ function useDirectorScreenSubscriptions(props: DirectorScreenProps): void {
419409
currentPartInstance: undefined,
420410
nextPartInstance: undefined,
421411
previousPartInstance: undefined,
422-
partInstanceToCountTimeFrom: undefined,
423412
}
424413
)
425414

426415
useSubscriptions(CorelibPubSub.pieceInstances, [
427416
currentPartInstance && [[currentPartInstance.rundownId], [currentPartInstance._id], {}],
428417
nextPartInstance && [[nextPartInstance.rundownId], [nextPartInstance._id], {}],
429-
firstTakenPartInstance && [[firstTakenPartInstance.rundownId], [firstTakenPartInstance._id], {}],
430418
])
431419
}
432420

@@ -448,7 +436,6 @@ function DirectorScreenRender({
448436
nextPartInstance,
449437
nextSegment,
450438
rundownIds,
451-
partInstanceToCountTimeFrom,
452439
}: Readonly<DirectorScreenProps & DirectorScreenTrackedProps>) {
453440
useSetDocumentClass('dark', 'xdark')
454441
const { t } = useTranslation()
@@ -575,7 +562,7 @@ function DirectorScreenRender({
575562

576563
return (
577564
<div className="director-screen">
578-
<DirectorScreenTop partInstanceToCountTimeFrom={partInstanceToCountTimeFrom} playlist={playlist} />
565+
<DirectorScreenTop playlist={playlist} />
579566
<div className="director-screen__body">
580567
{
581568
// Current Part:

0 commit comments

Comments
 (0)