-
-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
393 additions
and
179 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 61 additions & 14 deletions
75
apps/client/src/features/control/message/MessageControl.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,75 @@ | ||
.messageContainer { | ||
display: flex; | ||
flex-direction: column; | ||
gap: $section-spacing; | ||
.label { | ||
font-size: $inner-section-text-size; | ||
color: $label-gray; | ||
|
||
&.active { | ||
color: $action-text-color; | ||
} | ||
} | ||
|
||
.buttonSection { | ||
.previewContainer { | ||
display: grid; | ||
grid-template-columns: 1fr 1fr; | ||
gap: $element-spacing; | ||
margin-top: -0.5rem; | ||
grid-template-columns: 2fr 1fr; | ||
} | ||
|
||
.singleAction { | ||
.preview { | ||
background-color: $ui-black; | ||
display: grid; | ||
place-content: center; | ||
text-align: center; | ||
position: relative; | ||
} | ||
|
||
.options { | ||
display: flex; | ||
flex-direction: column; | ||
gap: $element-spacing; | ||
margin-top: $element-inner-spacing; | ||
} | ||
|
||
.label { | ||
font-size: $inner-section-text-size; | ||
color: $label-gray; | ||
.eventStatus { | ||
position: absolute; | ||
right: 0; | ||
margin: 0.5rem 0.25rem; | ||
display: flex; | ||
flex-direction: column; | ||
gap: 0.25rem; | ||
} | ||
|
||
&.active { | ||
color: $action-text-color; | ||
.mainContent { | ||
font-size: 1rem; | ||
font-weight: 600; | ||
color: var(--override-colour, $ui-white); | ||
|
||
&[data-phase='pending'] { | ||
color: $ontime-roll; | ||
} | ||
&[data-phase='overtime'] { | ||
color: $playback-negative; | ||
} | ||
} | ||
|
||
.secondaryContent { | ||
border-top: 1px solid $white-7; | ||
} | ||
|
||
.blackout { | ||
display: none; | ||
} | ||
|
||
.timerIndicators { | ||
display: flex; | ||
flex-direction: column; | ||
} | ||
|
||
.statusIcon { | ||
color: $gray-1000; | ||
|
||
&[data-active='true'] { | ||
color: $active-indicator; | ||
} | ||
} | ||
|
||
.divider { | ||
border-top: 1px solid $gray-1000; | ||
} |
66 changes: 16 additions & 50 deletions
66
apps/client/src/features/control/message/MessageControl.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,30 @@ | ||
import { Button } from '@chakra-ui/react'; | ||
import { IoEye } from '@react-icons/all-files/io5/IoEye'; | ||
import { IoEyeOffOutline } from '@react-icons/all-files/io5/IoEyeOffOutline'; | ||
import { IoSunny } from '@react-icons/all-files/io5/IoSunny'; | ||
import { IoSunnyOutline } from '@react-icons/all-files/io5/IoSunnyOutline'; | ||
|
||
import { setMessage, useMessageControl } from '../../../common/hooks/useSocket'; | ||
import { enDash } from '../../../common/utils/styleUtils'; | ||
|
||
import InputRow from './InputRow'; | ||
|
||
import style from './MessageControl.module.scss'; | ||
|
||
const noop = () => undefined; | ||
import TimerControlsPreview from './TimerViewControl'; | ||
|
||
export default function MessageControl() { | ||
const message = useMessageControl(); | ||
const blink = message.timer.blink; | ||
const blackout = message.timer.blackout; | ||
const { timer, external } = useMessageControl(); | ||
|
||
return ( | ||
<div className={style.messageContainer}> | ||
<> | ||
<TimerControlsPreview /> | ||
<InputRow | ||
label='Timer' | ||
placeholder='Message shown in stage timer' | ||
text={message.timer.text} | ||
visible={message.timer.visible} | ||
label='Timer message' | ||
placeholder='Message shown fullscreen in stage timer' | ||
text={timer.text} | ||
visible={timer.visible} | ||
changeHandler={(newValue) => setMessage.timerText(newValue)} | ||
actionHandler={() => setMessage.timerVisible(!message.timer.visible)} | ||
actionHandler={() => setMessage.timerVisible(!timer.visible)} | ||
/> | ||
<div className={style.buttonSection}> | ||
<Button | ||
size='sm' | ||
className={`${blink ? style.blink : ''}`} | ||
variant={blink ? 'ontime-filled' : 'ontime-subtle'} | ||
leftIcon={blink ? <IoSunny size='1rem' /> : <IoSunnyOutline size='1rem' />} | ||
onClick={() => setMessage.timerBlink(!blink)} | ||
data-testid='toggle timer blink' | ||
> | ||
Blink | ||
</Button> | ||
<Button | ||
size='sm' | ||
className={style.blackoutButton} | ||
variant={blackout ? 'ontime-filled' : 'ontime-subtle'} | ||
leftIcon={blackout ? <IoEye size='1rem' /> : <IoEyeOffOutline size='1rem' />} | ||
onClick={() => setMessage.timerBlackout(!blackout)} | ||
data-testid='toggle timer blackout' | ||
> | ||
Blackout screen | ||
</Button> | ||
</div> | ||
<InputRow | ||
label='External Message (read only)' | ||
placeholder={enDash} | ||
readonly | ||
text={message.external.text} | ||
visible={message.external.visible} | ||
changeHandler={noop} | ||
actionHandler={noop} | ||
label='External Message' | ||
placeholder='Message shown as secondary text in stage timer' | ||
text={external.text} | ||
visible={external.visible} | ||
changeHandler={(newValue) => setMessage.externalText(newValue)} | ||
actionHandler={() => setMessage.externalVisible(!external.visible)} | ||
/> | ||
</div> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { Tooltip } from '@chakra-ui/react'; | ||
import { IoArrowDown } from '@react-icons/all-files/io5/IoArrowDown'; | ||
import { IoArrowUp } from '@react-icons/all-files/io5/IoArrowUp'; | ||
import { IoFlag } from '@react-icons/all-files/io5/IoFlag'; | ||
import { IoTime } from '@react-icons/all-files/io5/IoTime'; | ||
import { TimerPhase, TimerType } from 'ontime-types'; | ||
|
||
import { useMessagePreview } from '../../../common/hooks/useSocket'; | ||
import useViewSettings from '../../../common/hooks-query/useViewSettings'; | ||
import { cx } from '../../../common/utils/styleUtils'; | ||
import { tooltipDelayMid } from '../../../ontimeConfig'; | ||
|
||
import style from './MessageControl.module.scss'; | ||
|
||
export default function TimerPreview() { | ||
const message = useMessagePreview(); | ||
const { data } = useViewSettings(); | ||
|
||
const contentClasses = cx([style.previewContent, message.blink && style.blink, message.blackout && style.blackout]); | ||
|
||
const showTimerMessage = message.messageVisible && message.messageHasContent; | ||
const showExternalMessage = message.externalVisible && message.externalHasContent; | ||
|
||
const main = (() => { | ||
if (showTimerMessage) { | ||
return 'Message'; | ||
} | ||
|
||
if (message.phase === TimerPhase.Pending) { | ||
return 'Standby to start'; | ||
} | ||
|
||
if (message.phase === TimerPhase.Overtime && data.endMessage) { | ||
return 'Custom end message'; | ||
} | ||
|
||
return 'Timer'; | ||
})(); | ||
|
||
const secondary = (() => { | ||
// message is a fullscreen overlay | ||
if (showTimerMessage) { | ||
return null; | ||
} | ||
|
||
// we need to check aux first since it takes priority | ||
if (message.secondary === 'aux') { | ||
return 'Aux Timer'; | ||
} | ||
|
||
if (message.secondary === 'external' && showExternalMessage) { | ||
return 'External message'; | ||
} | ||
|
||
return null; | ||
})(); | ||
|
||
const overrideColour = (() => { | ||
// override fallback colours from starter project | ||
if (message.phase === TimerPhase.Warning) { | ||
return data.warningColor ?? '#FFAB33'; | ||
} | ||
if (message.phase === TimerPhase.Danger) { | ||
return data.dangerColor ?? '#ED3333'; | ||
} | ||
return data.normalColor ?? '#FFFC'; | ||
})(); | ||
|
||
const showColourOverride = main == 'Timer'; | ||
|
||
return ( | ||
<div className={style.preview}> | ||
<div className={contentClasses}> | ||
<div | ||
className={style.mainContent} | ||
data-phase={message.phase} | ||
style={showColourOverride ? { '--override-colour': overrideColour } : {}} | ||
> | ||
{main} | ||
</div> | ||
{secondary !== null && <div className={style.secondaryContent}>{secondary}</div>} | ||
</div> | ||
<div className={style.eventStatus}> | ||
<Tooltip label='Time type: Count down' openDelay={tooltipDelayMid} shouldWrapChildren> | ||
<IoArrowDown className={style.statusIcon} data-active={message.timerType === TimerType.CountDown} /> | ||
</Tooltip> | ||
<Tooltip label='Time type: Count up' openDelay={tooltipDelayMid} shouldWrapChildren> | ||
<IoArrowUp className={style.statusIcon} data-active={message.timerType === TimerType.CountUp} /> | ||
</Tooltip> | ||
<Tooltip label='Time type: Clock' openDelay={tooltipDelayMid} shouldWrapChildren> | ||
<IoTime className={style.statusIcon} data-active={message.timerType === TimerType.Clock} /> | ||
</Tooltip> | ||
<Tooltip label='Time type: Time to end' openDelay={tooltipDelayMid} shouldWrapChildren> | ||
<IoFlag className={style.statusIcon} data-active={message.timerType === TimerType.TimeToEnd} /> | ||
</Tooltip> | ||
</div> | ||
</div> | ||
); | ||
} |
Oops, something went wrong.