mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-04 13:59:09 +00:00
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ontime-ui",
|
"name": "ontime-ui",
|
||||||
"version": "1.8.5",
|
"version": "1.9.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^2.3.2",
|
"@chakra-ui/react": "^2.3.2",
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { atomWithStorage } from 'jotai/utils';
|
||||||
|
|
||||||
|
export const mirrorViewersAtom = atomWithStorage('ontime-viewers-mirrorViewers', false);
|
||||||
@@ -4,10 +4,13 @@ import { IconButton } from '@chakra-ui/button';
|
|||||||
import { Image } from '@chakra-ui/react';
|
import { Image } from '@chakra-ui/react';
|
||||||
import { IoContract } from '@react-icons/all-files/io5/IoContract';
|
import { IoContract } from '@react-icons/all-files/io5/IoContract';
|
||||||
import { IoExpand } from '@react-icons/all-files/io5/IoExpand';
|
import { IoExpand } from '@react-icons/all-files/io5/IoExpand';
|
||||||
|
import { IoSync } from '@react-icons/all-files/io5/IoSync';
|
||||||
import navlogo from 'assets/images/logos/LOGO-72.png';
|
import navlogo from 'assets/images/logos/LOGO-72.png';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import { mirrorViewersAtom } from '../../atoms/ViewerSettings';
|
||||||
import useFullscreen from '../../hooks/useFullscreen';
|
import useFullscreen from '../../hooks/useFullscreen';
|
||||||
|
|
||||||
import navigatorConstants from './navigatorConstants';
|
import navigatorConstants from './navigatorConstants';
|
||||||
@@ -26,6 +29,7 @@ export default function NavLogo(props) {
|
|||||||
const { isHidden } = props;
|
const { isHidden } = props;
|
||||||
const [showNav, setShowNav] = useState(false);
|
const [showNav, setShowNav] = useState(false);
|
||||||
const { isFullScreen, toggleFullScreen } = useFullscreen();
|
const { isFullScreen, toggleFullScreen } = useFullscreen();
|
||||||
|
const [isMirrored, setMirrored] = useAtom(mirrorViewersAtom);
|
||||||
|
|
||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
setShowNav((prev) => !prev);
|
setShowNav((prev) => !prev);
|
||||||
@@ -57,6 +61,8 @@ export default function NavLogo(props) {
|
|||||||
tabIndex: 0,
|
tabIndex: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log('debug', isMirrored)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: showNav ? 0.5 : baseOpacity }}
|
initial={{ opacity: showNav ? 0.5 : baseOpacity }}
|
||||||
@@ -75,6 +81,12 @@ export default function NavLogo(props) {
|
|||||||
exit={{ opacity: 0, scaleX: 0 }}
|
exit={{ opacity: 0, scaleX: 0 }}
|
||||||
className={style.actions}
|
className={style.actions}
|
||||||
>
|
>
|
||||||
|
<IconButton
|
||||||
|
aria-label='Mirror screen'
|
||||||
|
icon={<IoSync />}
|
||||||
|
onClick={() => setMirrored((prev) => !prev)}
|
||||||
|
{...navButtonStyle}
|
||||||
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label='Toggle Fullscreen'
|
aria-label='Toggle Fullscreen'
|
||||||
icon={isFullScreen ? <IoContract /> : <IoExpand />}
|
icon={isFullScreen ? <IoContract /> : <IoExpand />}
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import Paginator from 'common/components/paginator/Paginator';
|
|||||||
import TitleSide from 'common/components/title-side/TitleSide';
|
import TitleSide from 'common/components/title-side/TitleSide';
|
||||||
import { formatDisplay } from 'common/utils/dateConfig';
|
import { formatDisplay } from 'common/utils/dateConfig';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||||
|
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||||
import { getEventsWithDelay } from '../../../common/utils/eventsManager';
|
import { getEventsWithDelay } from '../../../common/utils/eventsManager';
|
||||||
import { formatTime } from '../../../common/utils/time';
|
import { formatTime } from '../../../common/utils/time';
|
||||||
@@ -26,6 +28,7 @@ export default function Backstage(props) {
|
|||||||
const [filteredEvents, setFilteredEvents] = useState(null);
|
const [filteredEvents, setFilteredEvents] = useState(null);
|
||||||
const [pageNumber, setPageNumber] = useState(0);
|
const [pageNumber, setPageNumber] = useState(0);
|
||||||
const [currentPage, setCurrentPage] = useState(0);
|
const [currentPage, setCurrentPage] = useState(0);
|
||||||
|
const [isMirrored] = useAtom(mirrorViewersAtom);
|
||||||
|
|
||||||
// Set window title
|
// Set window title
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -58,7 +61,7 @@ export default function Backstage(props) {
|
|||||||
const clock = formatTime(time.clock, formatOptions);
|
const clock = formatTime(time.clock, formatOptions);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='backstage'>
|
<div className={`backstage ${isMirrored ? 'mirror' : ''}`}>
|
||||||
<NavLogo />
|
<NavLogo />
|
||||||
|
|
||||||
<div className='event-title'>{general.title}</div>
|
<div className='event-title'>{general.title}</div>
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
|
|
||||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||||
|
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||||
import NavLogo from '../../../common/components/nav/NavLogo';
|
import NavLogo from '../../../common/components/nav/NavLogo';
|
||||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||||
import {
|
import { TimeManager, ViewSettings } from '../../../common/models/OntimeTypes';
|
||||||
TimeManager,
|
|
||||||
ViewSettings,
|
|
||||||
} from '../../../common/models/OntimeTypes';
|
|
||||||
import { OverridableOptions } from '../../../common/models/ViewTypes';
|
import { OverridableOptions } from '../../../common/models/ViewTypes';
|
||||||
import { formatTime } from '../../../common/utils/time';
|
import { formatTime } from '../../../common/utils/time';
|
||||||
|
|
||||||
@@ -27,6 +26,7 @@ export default function Clock(props: ClockProps) {
|
|||||||
const { time, viewSettings } = props;
|
const { time, viewSettings } = props;
|
||||||
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
|
const [isMirrored] = useAtom(mirrorViewersAtom);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = 'ontime - Clock';
|
document.title = 'ontime - Clock';
|
||||||
@@ -127,7 +127,7 @@ export default function Clock(props: ClockProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className='clock-view'
|
className={`clock-view ${isMirrored ? 'mirror' : ''}`}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: userOptions.keyColour,
|
backgroundColor: userOptions.keyColour,
|
||||||
color: userOptions.textColour,
|
color: userOptions.textColour,
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Link, useSearchParams } from 'react-router-dom';
|
import { Link, useSearchParams } from 'react-router-dom';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||||
|
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||||
import NavLogo from '../../../common/components/nav/NavLogo';
|
import NavLogo from '../../../common/components/nav/NavLogo';
|
||||||
import Empty from '../../../common/components/state/Empty';
|
import Empty from '../../../common/components/state/Empty';
|
||||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||||
@@ -23,6 +25,7 @@ export default function Countdown(props) {
|
|||||||
const { backstageEvents, time, selectedId, viewSettings } = props;
|
const { backstageEvents, time, selectedId, viewSettings } = props;
|
||||||
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
|
const [isMirrored] = useAtom(mirrorViewersAtom);
|
||||||
|
|
||||||
const [follow, setFollow] = useState(null);
|
const [follow, setFollow] = useState(null);
|
||||||
const [runningTimer, setRunningTimer] = useState(0);
|
const [runningTimer, setRunningTimer] = useState(0);
|
||||||
@@ -90,7 +93,7 @@ export default function Countdown(props) {
|
|||||||
: formatTime(follow.timeEnd + delay, formatOptions);
|
: formatTime(follow.timeEnd + delay, formatOptions);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='countdown'>
|
<div className={`countdown ${isMirrored ? 'mirror' : ''}`}>
|
||||||
<NavLogo />
|
<NavLogo />
|
||||||
{follow === null ? (
|
{follow === null ? (
|
||||||
<div className='event-select'>
|
<div className='event-select'>
|
||||||
@@ -139,7 +142,7 @@ export default function Countdown(props) {
|
|||||||
>
|
>
|
||||||
{formatDisplay(
|
{formatDisplay(
|
||||||
isSelected ? runningTimer : runningTimer + millisToSeconds(delay),
|
isSelected ? runningTimer : runningTimer + millisToSeconds(delay),
|
||||||
isSelected || time.waiting
|
isSelected || time.waiting,
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
<div className='title'>{follow?.title || 'Untitled Event'}</div>
|
<div className='title'>{follow?.title || 'Untitled Event'}</div>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
|
|
||||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||||
|
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||||
import NavLogo from '../../../common/components/nav/NavLogo';
|
import NavLogo from '../../../common/components/nav/NavLogo';
|
||||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||||
import {
|
import {
|
||||||
@@ -24,6 +26,7 @@ export default function MinimalTimer(props: MinimalTimerProps) {
|
|||||||
const { pres, time, viewSettings } = props;
|
const { pres, time, viewSettings } = props;
|
||||||
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
|
const [isMirrored] = useAtom(mirrorViewersAtom);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = 'ontime - Minimal Timer';
|
document.title = 'ontime - Minimal Timer';
|
||||||
@@ -131,9 +134,11 @@ export default function MinimalTimer(props: MinimalTimerProps) {
|
|||||||
const clean = timer.replace('/:/g', '');
|
const clean = timer.replace('/:/g', '');
|
||||||
const showFinished = time.isNegative && !userOptions?.hideOvertime;
|
const showFinished = time.isNegative && !userOptions?.hideOvertime;
|
||||||
|
|
||||||
|
const baseClasses = `minimal-timer ${isMirrored ? 'mirror' : ''}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={showFinished ? 'minimal-timer minimal-timer--finished' : 'minimal-timer'}
|
className={showFinished ? `${baseClasses} minimal-timer--finished` : baseClasses}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: userOptions.keyColour,
|
backgroundColor: userOptions.keyColour,
|
||||||
color: userOptions.textColour,
|
color: userOptions.textColour,
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet
|
|||||||
import { formatTime } from '../../../common/utils/time';
|
import { formatTime } from '../../../common/utils/time';
|
||||||
|
|
||||||
import './Pip.scss';
|
import './Pip.scss';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
|
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||||
|
|
||||||
const formatOptions = {
|
const formatOptions = {
|
||||||
showSeconds: true,
|
showSeconds: true,
|
||||||
@@ -25,6 +27,7 @@ export default function Pip(props) {
|
|||||||
const [filteredEvents, setFilteredEvents] = useState(null);
|
const [filteredEvents, setFilteredEvents] = useState(null);
|
||||||
const [pageNumber, setPageNumber] = useState(0);
|
const [pageNumber, setPageNumber] = useState(0);
|
||||||
const [currentPage, setCurrentPage] = useState(0);
|
const [currentPage, setCurrentPage] = useState(0);
|
||||||
|
const [isMirrored] = useAtom(mirrorViewersAtom);
|
||||||
|
|
||||||
// Set window title
|
// Set window title
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -65,7 +68,7 @@ export default function Pip(props) {
|
|||||||
const clock = formatTime(time.clock, formatOptions);
|
const clock = formatTime(time.clock, formatOptions);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='pip'>
|
<div className={`pip ${isMirrored ? 'mirror' : ''}`}>
|
||||||
<NavLogo />
|
<NavLogo />
|
||||||
|
|
||||||
<div className='event-title'>{general.title}</div>
|
<div className='event-title'>{general.title}</div>
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import NavLogo from 'common/components/nav/NavLogo';
|
|||||||
import Paginator from 'common/components/paginator/Paginator';
|
import Paginator from 'common/components/paginator/Paginator';
|
||||||
import TitleSide from 'common/components/title-side/TitleSide';
|
import TitleSide from 'common/components/title-side/TitleSide';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||||
|
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||||
import { formatTime } from '../../../common/utils/time';
|
import { formatTime } from '../../../common/utils/time';
|
||||||
import { titleVariants } from '../common/animation';
|
import { titleVariants } from '../common/animation';
|
||||||
@@ -23,6 +25,7 @@ export default function Public(props) {
|
|||||||
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
||||||
const [pageNumber, setPageNumber] = useState(0);
|
const [pageNumber, setPageNumber] = useState(0);
|
||||||
const [currentPage, setCurrentPage] = useState(0);
|
const [currentPage, setCurrentPage] = useState(0);
|
||||||
|
const [isMirrored] = useAtom(mirrorViewersAtom);
|
||||||
|
|
||||||
// Set window title
|
// Set window title
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -40,7 +43,7 @@ export default function Public(props) {
|
|||||||
const clock = formatTime(time.clock, formatOptions);
|
const clock = formatTime(time.clock, formatOptions);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='public-screen'>
|
<div className={`public-screen ${isMirrored ? 'mirror' : ''}`}>
|
||||||
<NavLogo />
|
<NavLogo />
|
||||||
|
|
||||||
<div className='event-title'>{general.title}</div>
|
<div className='event-title'>{general.title}</div>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||||
|
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||||
import NavLogo from '../../../common/components/nav/NavLogo';
|
import NavLogo from '../../../common/components/nav/NavLogo';
|
||||||
import useFitText from '../../../common/hooks/useFitText';
|
import useFitText from '../../../common/hooks/useFitText';
|
||||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||||
@@ -28,6 +30,7 @@ export default function StudioClock(props) {
|
|||||||
const { fontSize: titleFontSize, ref: titleRef } = useFitText({ maxFontSize: 500 });
|
const { fontSize: titleFontSize, ref: titleRef } = useFitText({ maxFontSize: 500 });
|
||||||
|
|
||||||
const [schedule, setSchedule] = useState([]);
|
const [schedule, setSchedule] = useState([]);
|
||||||
|
const [isMirrored] = useAtom(mirrorViewersAtom);
|
||||||
|
|
||||||
const activeIndicators = [...Array(12).keys()];
|
const activeIndicators = [...Array(12).keys()];
|
||||||
const secondsIndicators = [...Array(60).keys()];
|
const secondsIndicators = [...Array(60).keys()];
|
||||||
@@ -48,13 +51,13 @@ export default function StudioClock(props) {
|
|||||||
showEnd: false,
|
showEnd: false,
|
||||||
});
|
});
|
||||||
setSchedule(formatted);
|
setSchedule(formatted);
|
||||||
}, [backstageEvents, nextId, selectedId] );
|
}, [backstageEvents, nextId, selectedId]);
|
||||||
|
|
||||||
const clock = formatTime(time.clock, formatOptions);
|
const clock = formatTime(time.clock, formatOptions);
|
||||||
const [, , secondsNow] = stringFromMillis(time.clock).split(':');
|
const [, , secondsNow] = stringFromMillis(time.clock).split(':');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='studio-clock'>
|
<div className={`studio-clock ${isMirrored ? 'mirror' : ''}`}>
|
||||||
<NavLogo />
|
<NavLogo />
|
||||||
<div className='clock-container'>
|
<div className='clock-container'>
|
||||||
<div className='studio-timer'>{clock}</div>
|
<div className='studio-timer'>{clock}</div>
|
||||||
@@ -65,7 +68,8 @@ export default function StudioClock(props) {
|
|||||||
>
|
>
|
||||||
{title.titleNext}
|
{title.titleNext}
|
||||||
</div>
|
</div>
|
||||||
<div className={time.isNegative ? 'next-countdown' : 'next-countdown next-countdown--overtime'}>
|
<div
|
||||||
|
className={time.isNegative ? 'next-countdown' : 'next-countdown next-countdown--overtime'}>
|
||||||
{selectedId != null && formatDisplay(time.running)}
|
{selectedId != null && formatDisplay(time.running)}
|
||||||
</div>
|
</div>
|
||||||
<div className='clock-indicators'>
|
<div className='clock-indicators'>
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import MyProgressBar from 'common/components/myProgressBar/MyProgressBar';
|
|||||||
import NavLogo from 'common/components/nav/NavLogo';
|
import NavLogo from 'common/components/nav/NavLogo';
|
||||||
import TitleCard from 'common/components/title-card/TitleCard';
|
import TitleCard from 'common/components/title-card/TitleCard';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
import { overrideStylesURL } from '../../../common/api/apiConstants';
|
||||||
|
import { mirrorViewersAtom } from '../../../common/atoms/ViewerSettings';
|
||||||
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
import { useRuntimeStylesheet } from '../../../common/hooks/useRuntimeStylesheet';
|
||||||
import { formatTime } from '../../../common/utils/time';
|
import { formatTime } from '../../../common/utils/time';
|
||||||
|
|
||||||
@@ -23,6 +25,7 @@ export default function Timer(props) {
|
|||||||
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
||||||
const [elapsed, setElapsed] = useState(true);
|
const [elapsed, setElapsed] = useState(true);
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
|
const [isMirrored] = useAtom(mirrorViewersAtom);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = 'ontime - Timer';
|
document.title = 'ontime - Timer';
|
||||||
@@ -64,9 +67,10 @@ export default function Timer(props) {
|
|||||||
y: 500,
|
y: 500,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
const baseClasses = `stage-timer ${isMirrored ? 'mirror' : ''}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={time.finished ? 'stage-timer stage-timer--finished' : 'stage-timer'}>
|
<div className={time.finished ? `${baseClasses} stage-timer--finished` : baseClasses}>
|
||||||
<div className={showOverlay ? 'message-overlay message-overlay--active' : 'message-overlay'}>
|
<div className={showOverlay ? 'message-overlay message-overlay--active' : 'message-overlay'}>
|
||||||
<div className='message'>{pres.text}</div>
|
<div className='message'>{pres.text}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.mirror {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
@use 'main' as *;
|
@use 'main' as *;
|
||||||
|
@use 'viewerCommon' as *;
|
||||||
|
|
||||||
// General styling
|
// General styling
|
||||||
$accent-color: $ontime-pink; // --accent-color-override
|
$accent-color: $ontime-pink; // --accent-color-override
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ontime",
|
"name": "ontime",
|
||||||
"version": "1.8.5",
|
"version": "1.9.0",
|
||||||
"author": "Carlos Valente",
|
"author": "Carlos Valente",
|
||||||
"description": "Time keeping for live events",
|
"description": "Time keeping for live events",
|
||||||
"repository": "https://github.com/cpvalente/ontime",
|
"repository": "https://github.com/cpvalente/ontime",
|
||||||
|
|||||||
Reference in New Issue
Block a user