mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-15 12:23:51 +00:00
Merge branch 'master' into wip/migratedb
This commit is contained in:
@@ -41,10 +41,7 @@ const Transport = ({ selectedId, playbackControl }) => {
|
||||
<div className={style.playbackContainer}>
|
||||
<PrevIconBtn clickhandler={() => playbackControl('previous')} />
|
||||
<NextIconBtn clickhandler={() => playbackControl('next')} />
|
||||
<UnloadIconBtn
|
||||
clickhandler={() => playbackControl('unload')}
|
||||
disabled={!selectedId}
|
||||
/>
|
||||
<UnloadIconBtn clickhandler={() => playbackControl('unload')} />
|
||||
<ReloadIconButton
|
||||
clickhandler={() => playbackControl('reload')}
|
||||
disabled={!selectedId}
|
||||
|
||||
@@ -90,6 +90,7 @@ export default function PlaybackControl() {
|
||||
<div className={style.mainContainer}>
|
||||
<PlaybackTimer
|
||||
timer={timer}
|
||||
playback={playback}
|
||||
handleIncrement={(amount) => socket.emit('increment-timer', amount)}
|
||||
/>
|
||||
<PlaybackButtons
|
||||
|
||||
@@ -35,18 +35,19 @@
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.indRoll,
|
||||
.indDelay,
|
||||
.indNegative {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.indRoll,
|
||||
.indRollActive,
|
||||
.indDelay {
|
||||
margin: 0 auto;
|
||||
border-radius: 50%;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
@@ -60,7 +61,7 @@
|
||||
.indNegativeActive {
|
||||
margin: 0 auto;
|
||||
width: 90%;
|
||||
height: 0.3em
|
||||
height: 0.3em;
|
||||
}
|
||||
|
||||
.indNegativeActive {
|
||||
|
||||
@@ -8,16 +8,18 @@ const areEqual = (prevProps, nextProps) => {
|
||||
return (
|
||||
prevProps.timer.running === nextProps.timer.running &&
|
||||
prevProps.timer.expectedFinish === nextProps.timer.expectedFinish &&
|
||||
prevProps.timer.startedAt === nextProps.timer.startedAt
|
||||
prevProps.timer.startedAt === nextProps.timer.startedAt &&
|
||||
prevProps.playback === nextProps.playback
|
||||
);
|
||||
};
|
||||
|
||||
const PlaybackTimer = ({ timer, handleIncrement }) => {
|
||||
const PlaybackTimer = (props) => {
|
||||
const { timer, playback, handleIncrement } = props;
|
||||
const started = stringFromMillis(timer.startedAt, true);
|
||||
const finish = stringFromMillis(timer.expectedFinish, true);
|
||||
const isNegative = timer.running < 0;
|
||||
const isDelayed = false;
|
||||
const isRolling = false;
|
||||
const isRolling = playback === 'roll';
|
||||
|
||||
const incrementProps = {
|
||||
size: 'sm',
|
||||
@@ -31,7 +33,7 @@ const PlaybackTimer = ({ timer, handleIncrement }) => {
|
||||
<>
|
||||
<div className={style.timeContainer}>
|
||||
<div className={style.indicators}>
|
||||
<div className={style.indRoll} />
|
||||
<div className={isRolling ? style.indRollActive : style.indRoll} />
|
||||
<div
|
||||
className={isNegative ? style.indNegativeActive : style.indNegative}
|
||||
/>
|
||||
@@ -49,16 +51,32 @@ const PlaybackTimer = ({ timer, handleIncrement }) => {
|
||||
<span className={style.time}>{finish}</span>
|
||||
</div>
|
||||
<div className={style.btn}>
|
||||
<Button {...incrementProps} onClick={() => handleIncrement(-1)}>
|
||||
<Button
|
||||
{...incrementProps}
|
||||
disabled={isRolling}
|
||||
onClick={() => handleIncrement(-1)}
|
||||
>
|
||||
-1
|
||||
</Button>
|
||||
<Button {...incrementProps} onClick={() => handleIncrement(1)}>
|
||||
<Button
|
||||
{...incrementProps}
|
||||
disabled={isRolling}
|
||||
onClick={() => handleIncrement(1)}
|
||||
>
|
||||
+1
|
||||
</Button>
|
||||
<Button {...incrementProps} onClick={() => handleIncrement(-5)}>
|
||||
<Button
|
||||
{...incrementProps}
|
||||
disabled={isRolling}
|
||||
onClick={() => handleIncrement(-5)}
|
||||
>
|
||||
-5
|
||||
</Button>
|
||||
<Button {...incrementProps} onClick={() => handleIncrement(5)}>
|
||||
<Button
|
||||
{...incrementProps}
|
||||
disabled={isRolling}
|
||||
onClick={() => handleIncrement(5)}
|
||||
>
|
||||
+5
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -18,11 +18,12 @@
|
||||
/* 2/3 window, hide previews */
|
||||
@media (max-width: 1250px) and (min-height: 700px) {
|
||||
.mainContainer {
|
||||
height: 100%;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
grid-template-columns: 48em 1fr 1fr;
|
||||
grid-template-areas:
|
||||
/* grid-template-areas:
|
||||
'even play sett'
|
||||
'even mess sett';
|
||||
'even mess sett'; */
|
||||
}
|
||||
|
||||
.info {
|
||||
@@ -40,6 +41,11 @@
|
||||
'play';
|
||||
}
|
||||
|
||||
.messages,
|
||||
.playback {
|
||||
min-width: 31em;
|
||||
}
|
||||
|
||||
.editor,
|
||||
.info,
|
||||
.settings {
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function ActionButtons(props) {
|
||||
aria-label='Options'
|
||||
size='xs'
|
||||
icon={<FiZap />}
|
||||
_expanded={{ bg: 'pink.300', color: 'white' }}
|
||||
_expanded={{ bg: 'orange.300', color: 'white' }}
|
||||
_focus={{ boxShadow: 'none' }}
|
||||
backgroundColor={'orange.200'}
|
||||
color={'orange.500'}
|
||||
|
||||
@@ -14,7 +14,8 @@ import { SelectCollapse, HandleCollapse } from 'app/context/collapseAtom';
|
||||
import { useAtom } from 'jotai';
|
||||
|
||||
const ExpandedBlock = (props) => {
|
||||
const { provided, data, next, delay, delayValue, actionHandler } = props;
|
||||
const { provided, data, eventIndex, next, delay, delayValue, actionHandler } =
|
||||
props;
|
||||
|
||||
const oscid = data.id.length > 4 ? '...' : data.id;
|
||||
|
||||
@@ -80,7 +81,9 @@ const ExpandedBlock = (props) => {
|
||||
actionHandler('update', { field: 'note', value: v })
|
||||
}
|
||||
/>
|
||||
<span className={style.oscLabel}>{`OSC ID: ${oscid}`}</span>
|
||||
<span className={style.oscLabel}>
|
||||
{`/ontime/goto ${eventIndex + 1} << OSC >> /ontime/gotoid ${oscid}`}
|
||||
</span>
|
||||
</div>
|
||||
<Icon
|
||||
className={style.more}
|
||||
@@ -156,7 +159,7 @@ const CollapsedBlock = (props) => {
|
||||
};
|
||||
|
||||
export default function EventBlock(props) {
|
||||
const { data, selected, delay, index, actionHandler } = props;
|
||||
const { data, selected, delay, index, eventIndex, actionHandler } = props;
|
||||
|
||||
// const [collapsed, setCollapsed] = useState(checkLocalStorage(data.id));
|
||||
|
||||
@@ -200,6 +203,7 @@ export default function EventBlock(props) {
|
||||
) : (
|
||||
<ExpandedBlock
|
||||
provided={provided}
|
||||
eventIndex={eventIndex}
|
||||
data={data}
|
||||
next={props.next}
|
||||
delay={delay}
|
||||
|
||||
@@ -27,7 +27,7 @@ export default function EventList(props) {
|
||||
},
|
||||
'Alt+ArrowUp': () => {
|
||||
if (cursor == null) setCursor(0);
|
||||
else if (cursor >= 0) setCursor(cursor - 1);
|
||||
else if (cursor > 0) setCursor(cursor - 1);
|
||||
},
|
||||
'Alt+KeyE': (event) => {
|
||||
event.preventDefault();
|
||||
@@ -49,7 +49,7 @@ export default function EventList(props) {
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
}, [cursor, events.length, eventsHandler]);
|
||||
}, [cursor, events, eventsHandler]);
|
||||
|
||||
// handle incoming messages
|
||||
useEffect(() => {
|
||||
@@ -62,7 +62,6 @@ export default function EventList(props) {
|
||||
// Handle playstate
|
||||
socket.on('selected', (data) => {
|
||||
setSelected(data);
|
||||
console.log('debug cursor setted', data);
|
||||
});
|
||||
socket.on('next-id', (data) => {
|
||||
setNext(data);
|
||||
@@ -80,13 +79,20 @@ export default function EventList(props) {
|
||||
if (cursorSettings !== 'locked' || selected == null) return;
|
||||
if (selected.index == null) return;
|
||||
|
||||
setCursor(selected.index);
|
||||
}, [selected, cursorSettings]);
|
||||
let eventIndex = -1;
|
||||
let gotoIndex = -1;
|
||||
for (const e of events) {
|
||||
gotoIndex++;
|
||||
if (e.type === 'event') eventIndex++;
|
||||
if (eventIndex === selected.index) break;
|
||||
}
|
||||
|
||||
setCursor(gotoIndex);
|
||||
}, [events, selected, cursorSettings]);
|
||||
|
||||
// attach scroll to cursor
|
||||
useEffect(() => {
|
||||
if (cursor == null || cursorRef.current == null) return;
|
||||
console.log('debug cursor scrolling');
|
||||
|
||||
cursorRef.current.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
@@ -117,8 +123,7 @@ export default function EventList(props) {
|
||||
|
||||
console.log('EventList: events in event list', events);
|
||||
let cumulativeDelay = 0;
|
||||
|
||||
console.log('debug selected', selected);
|
||||
let eventIndex = -1;
|
||||
|
||||
return (
|
||||
<div className={style.eventContainer}>
|
||||
@@ -131,20 +136,28 @@ export default function EventList(props) {
|
||||
ref={provided.innerRef}
|
||||
>
|
||||
{events.map((e, index) => {
|
||||
let isCursor = cursor === index;
|
||||
if (index === 0) cumulativeDelay = 0;
|
||||
if (index === 0) {
|
||||
cumulativeDelay = 0;
|
||||
eventIndex = -1;
|
||||
}
|
||||
if (e.type === 'delay' && e.duration != null) {
|
||||
cumulativeDelay += e.duration;
|
||||
} else if (e.type === 'block') cumulativeDelay = 0;
|
||||
} else if (e.type === 'block') {
|
||||
cumulativeDelay = 0;
|
||||
} else if (e.type === 'event') {
|
||||
eventIndex++;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={isCursor ? cursorRef : undefined}
|
||||
ref={cursor === index ? cursorRef : undefined}
|
||||
key={e.id}
|
||||
className={isCursor ? style.cursor : undefined}
|
||||
className={cursor === index ? style.cursor : undefined}
|
||||
>
|
||||
<EventListItem
|
||||
type={e.type}
|
||||
index={index}
|
||||
eventIndex={eventIndex}
|
||||
data={e}
|
||||
selected={selected?.id === e.id}
|
||||
next={next === e.id}
|
||||
|
||||
@@ -18,6 +18,7 @@ const EventListItem = (props) => {
|
||||
const {
|
||||
type,
|
||||
index,
|
||||
eventIndex,
|
||||
data,
|
||||
selected,
|
||||
next,
|
||||
@@ -71,6 +72,7 @@ const EventListItem = (props) => {
|
||||
return (
|
||||
<EventBlock
|
||||
index={index}
|
||||
eventIndex={eventIndex}
|
||||
data={data}
|
||||
selected={selected}
|
||||
next={next}
|
||||
|
||||
@@ -23,7 +23,7 @@ export default function MenuActionButtons(props) {
|
||||
aria-label='Options'
|
||||
size={props.size || 'xs'}
|
||||
icon={<FiZap />}
|
||||
_expanded={{ bg: 'pink.300', color: 'white' }}
|
||||
_expanded={{ bg: 'orange.300', color: 'white' }}
|
||||
_focus={{ boxShadow: 'none' }}
|
||||
backgroundColor={'orange.200'}
|
||||
color={'orange.500'}
|
||||
|
||||
@@ -37,7 +37,7 @@ const withSocket = (Component) => {
|
||||
});
|
||||
const [timer, setTimer] = useState({
|
||||
clock: null,
|
||||
currentSeconds: null,
|
||||
running: null,
|
||||
startedAt: null,
|
||||
expectedFinish: null,
|
||||
});
|
||||
@@ -221,7 +221,7 @@ const withSocket = (Component) => {
|
||||
// get clock string
|
||||
const timeManager = {
|
||||
...timer,
|
||||
finished: timer.running <= 0 && timer.startedAt,
|
||||
finished: playback === 'start' && timer.running <= 0 && timer.startedAt,
|
||||
clock: stringFromMillis(timer.clock),
|
||||
playstate: playback,
|
||||
};
|
||||
|
||||
@@ -42,7 +42,7 @@ export default function StageManager(props) {
|
||||
// Format messages
|
||||
const showPubl = publ.text !== '' && publ.visible;
|
||||
let stageTimer = formatDisplay(Math.abs(time.running), true);
|
||||
if (time.running < 0) stageTimer = '-' + stageTimer;
|
||||
if (time.running < 0) stageTimer = `-${stageTimer}`;
|
||||
|
||||
// motion
|
||||
const titleVariants = {
|
||||
|
||||
@@ -14,10 +14,9 @@ export default function PresenterView(props) {
|
||||
document.title = 'ontime - Speaker Screen';
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
const showOverlay = pres.text !== '' && pres.visible;
|
||||
const isPlaying = time.playstate === 'start';
|
||||
const isPlaying = time.playstate !== 'pause';
|
||||
const normalisedTime = Math.max(time.running, 0);
|
||||
|
||||
// motion
|
||||
const titleVariants = {
|
||||
@@ -61,7 +60,7 @@ export default function PresenterView(props) {
|
||||
<div className={style.finished}>TIME UP</div>
|
||||
) : (
|
||||
<div className={isPlaying ? style.countdown : style.countdownPaused}>
|
||||
<Countdown time={time.currentSeconds} hideZeroHours />
|
||||
<Countdown time={normalisedTime} hideZeroHours />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -73,7 +72,7 @@ export default function PresenterView(props) {
|
||||
}
|
||||
>
|
||||
<MyProgressBar
|
||||
now={time.currentSeconds}
|
||||
now={normalisedTime}
|
||||
complete={time.durationSeconds}
|
||||
showElapsed
|
||||
/>
|
||||
|
||||
@@ -51,11 +51,8 @@ export default function Pip(props) {
|
||||
// Format messages
|
||||
const showInfo =
|
||||
general.backstageInfo !== '' && general.backstageInfo != null;
|
||||
|
||||
const stageTimer =
|
||||
time.currentSeconds != null && !isNaN(time.currentSeconds)
|
||||
? formatDisplay(time.currentSeconds, true)
|
||||
: '';
|
||||
let stageTimer = formatDisplay(Math.abs(time.running), true);
|
||||
if (time.running < 0) stageTimer = `-${stageTimer}`;
|
||||
|
||||
return (
|
||||
<div className={style.container__gray}>
|
||||
|
||||
Reference in New Issue
Block a user