mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-31 20:09:11 +00:00
c4ac9df8cf
Three adjustments to the panel layout: - the timer status icons go back to overlaying the stage, which returns the row they were costing. They sit in the same chrome layer as the pop-out buttons, so the blackout no longer hides them - the screen state buttons group with the preview they act on, and the gap before the message inputs widens to separate the two - the stage drops its fixed aspect ratio and fills the panel width, which also removes the slack a tall panel used to leave around it Without a 16:9 frame the width derived font size can overflow a short, wide stage, so the timer is now capped by container height at the ratio the estimate assumes. In the pip window, which has no ancestor query container, both terms resolve against the viewport, so a 16:9 window is unchanged and a wider one stops clipping its digits. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011CHxSQ6nWHuyar8feieRra
116 lines
4.0 KiB
TypeScript
116 lines
4.0 KiB
TypeScript
import { ViewSettings } from 'ontime-types';
|
|
|
|
import { FitText } from '../../../common/components/fit-text/FitText';
|
|
import MultiPartProgressBar from '../../../common/components/multi-part-progress-bar/MultiPartProgressBar';
|
|
import { useTimerSocket } from '../../../common/hooks/useSocket';
|
|
import { cx } from '../../../common/utils/styleUtils';
|
|
import { getFormattedTimer, getTimerByType } from '../../common/viewUtils';
|
|
import {
|
|
getEstimatedFontSize,
|
|
getIsPlaying,
|
|
getSecondaryDisplay,
|
|
getShowMessage,
|
|
getShowModifiers,
|
|
getShowProgressBar,
|
|
getTotalTime,
|
|
} from '../../timer/timer.utils';
|
|
import { getTimerColour } from '../../utils/presentation.utils';
|
|
|
|
import './PipTimer.scss';
|
|
|
|
interface PipTimerProps {
|
|
viewSettings: ViewSettings;
|
|
}
|
|
|
|
export function PipTimer({ viewSettings }: PipTimerProps) {
|
|
const { eventNow, message, time, clock, timerTypeNow, countToEndNow, auxTimer } = useTimerSocket();
|
|
|
|
// gather modifiers
|
|
const showOverlay = getShowMessage(message.timer);
|
|
const { showFinished, showWarning, showDanger } = getShowModifiers(
|
|
timerTypeNow,
|
|
countToEndNow,
|
|
time.phase,
|
|
false,
|
|
'',
|
|
false,
|
|
);
|
|
const isPlaying = getIsPlaying(time.playback);
|
|
const showProgressBar = getShowProgressBar(timerTypeNow);
|
|
|
|
// gather timer data
|
|
const totalTime = getTotalTime(time.duration, time.addedTime);
|
|
const stageTimer = getTimerByType(false, timerTypeNow, clock, time, timerTypeNow);
|
|
// match the defaults of the timer view, which is what the preview is standing in for
|
|
const display = getFormattedTimer(stageTimer, timerTypeNow, 'min', {
|
|
removeSeconds: false,
|
|
removeLeadingZero: true,
|
|
});
|
|
|
|
const currentAux = (() => {
|
|
if (message.timer.secondarySource === 'aux1') {
|
|
return auxTimer.aux1;
|
|
}
|
|
if (message.timer.secondarySource === 'aux2') {
|
|
return auxTimer.aux2;
|
|
}
|
|
if (message.timer.secondarySource === 'aux3') {
|
|
return auxTimer.aux3;
|
|
}
|
|
return null;
|
|
})();
|
|
|
|
const secondaryContent = getSecondaryDisplay(message, currentAux, 'min', false, true, false);
|
|
|
|
// gather presentation styles
|
|
const resolvedTimerColour = getTimerColour(viewSettings, undefined, showWarning, showDanger);
|
|
// the estimate is tuned for a 16:9 screen, so cap it by height for containers wider than that
|
|
const timerFontSize = getEstimatedFontSize(display, secondaryContent);
|
|
const timerFontRule = `min(${timerFontSize}cqw, ${((timerFontSize * 16) / 9).toFixed(2)}cqh)`;
|
|
const userStyles = {
|
|
...(resolvedTimerColour && { '--timer-colour': resolvedTimerColour }),
|
|
};
|
|
|
|
return (
|
|
<div className={cx(['pip-timer', showFinished && 'pip-timer--finished'])} style={userStyles}>
|
|
<div className={cx(['blackout', message.timer.blackout && 'blackout--active'])} />
|
|
|
|
<div className={cx(['message-overlay', showOverlay && 'message-overlay--active'])}>
|
|
<FitText mode='multi' min={12} max={256} className={cx(['message', message.timer.blink && 'blink'])}>
|
|
{message.timer.text}
|
|
</FitText>
|
|
</div>
|
|
|
|
<div className={cx(['timer-container', message.timer.blink && !showOverlay && 'blink'])}>
|
|
<div
|
|
className={cx(['timer', !isPlaying && 'timer--paused', showFinished && 'timer--finished'])}
|
|
style={{ fontSize: timerFontRule }}
|
|
data-phase={time.phase}
|
|
>
|
|
{display}
|
|
</div>
|
|
<div className={cx(['secondary', !secondaryContent && 'secondary--hidden'])}>
|
|
<FitText mode='multi' min={12} max={256}>
|
|
{secondaryContent}
|
|
</FitText>
|
|
</div>
|
|
</div>
|
|
|
|
{showProgressBar && (
|
|
<MultiPartProgressBar
|
|
className={cx(['progress-container', !isPlaying && 'progress-container--paused'])}
|
|
now={time.current}
|
|
complete={totalTime}
|
|
eventId={eventNow?.id}
|
|
normalColor={viewSettings.normalColor}
|
|
warning={eventNow?.timeWarning}
|
|
warningColor={viewSettings.warningColor}
|
|
danger={eventNow?.timeDanger}
|
|
dangerColor={viewSettings.dangerColor}
|
|
hideOvertime={!showFinished}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|