mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-19 22:24:11 +00:00
refactor: extract studio data to hook
This commit is contained in:
committed by
Carlos Valente
parent
ad7f658f15
commit
bea7e2bb2b
@@ -69,6 +69,7 @@ export default function AppRouter() {
|
|||||||
path='studio'
|
path='studio'
|
||||||
element={
|
element={
|
||||||
<ViewLoader>
|
<ViewLoader>
|
||||||
|
<ViewNavigationMenu isLockable />
|
||||||
<StudioClock />
|
<StudioClock />
|
||||||
</ViewLoader>
|
</ViewLoader>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -256,3 +256,16 @@ export const useBackstageSocket = createSelector((state: RuntimeStore) => ({
|
|||||||
selectedEventId: state.eventNow?.id ?? null,
|
selectedEventId: state.eventNow?.id ?? null,
|
||||||
time: state.timer,
|
time: state.timer,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export const useStudioClockSocket = createSelector((state: RuntimeStore) => ({
|
||||||
|
clock: state.clock,
|
||||||
|
playback: state.timer.playback,
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const useStudioTimersSocket = createSelector((state: RuntimeStore) => ({
|
||||||
|
eventNext: state.eventNext,
|
||||||
|
eventNow: state.eventNow,
|
||||||
|
message: state.message,
|
||||||
|
time: state.timer,
|
||||||
|
runtime: state.runtime,
|
||||||
|
}));
|
||||||
|
|||||||
@@ -1,45 +1,38 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { MessageState, OntimeEvent, OntimeView, ProjectData, Runtime, Settings, ViewSettings } from 'ontime-types';
|
import { OntimeView } from 'ontime-types';
|
||||||
|
|
||||||
|
import EmptyPage from '../../common/components/state/EmptyPage';
|
||||||
import ViewLogo from '../../common/components/view-logo/ViewLogo';
|
import ViewLogo from '../../common/components/view-logo/ViewLogo';
|
||||||
import ViewParamsEditor from '../../common/components/view-params-editor/ViewParamsEditor';
|
import ViewParamsEditor from '../../common/components/view-params-editor/ViewParamsEditor';
|
||||||
import { useWindowTitle } from '../../common/hooks/useWindowTitle';
|
import { useWindowTitle } from '../../common/hooks/useWindowTitle';
|
||||||
import type { ViewExtendedTimer } from '../../common/models/TimeManager.type';
|
|
||||||
import { cx } from '../../common/utils/styleUtils';
|
import { cx } from '../../common/utils/styleUtils';
|
||||||
import { getDefaultFormat } from '../../common/utils/time';
|
import { getDefaultFormat } from '../../common/utils/time';
|
||||||
|
import Loader from '../common/loader/Loader';
|
||||||
|
|
||||||
import { getStudioOptions, useStudioOptions } from './studio.options';
|
import { getStudioOptions, useStudioOptions } from './studio.options';
|
||||||
import StudioClock from './StudioClock';
|
import StudioClock from './StudioClock';
|
||||||
import StudioTimers from './StudioTimers';
|
import StudioTimers from './StudioTimers';
|
||||||
|
import { StudioData, useStudioData } from './useStudioData';
|
||||||
|
|
||||||
import './Studio.scss';
|
import './Studio.scss';
|
||||||
|
|
||||||
interface StudioProps {
|
export default function StudioLoader() {
|
||||||
eventNow: OntimeEvent | null;
|
const { data, status } = useStudioData();
|
||||||
eventNext: OntimeEvent | null;
|
|
||||||
general: ProjectData;
|
useWindowTitle('Studio Clock');
|
||||||
isMirrored: boolean;
|
|
||||||
message: MessageState;
|
if (status === 'pending') {
|
||||||
time: ViewExtendedTimer;
|
return <Loader />;
|
||||||
runtime: Runtime;
|
}
|
||||||
onAir: boolean;
|
|
||||||
settings: Settings | undefined;
|
if (status === 'error') {
|
||||||
viewSettings: ViewSettings;
|
return <EmptyPage text='There was an error fetching data, please refresh the page.' />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Studio {...data} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Studio({
|
function Studio({ projectData, isMirrored, settings, viewSettings }: StudioData) {
|
||||||
eventNow,
|
|
||||||
eventNext,
|
|
||||||
general,
|
|
||||||
isMirrored,
|
|
||||||
message,
|
|
||||||
time,
|
|
||||||
runtime,
|
|
||||||
onAir,
|
|
||||||
settings,
|
|
||||||
viewSettings,
|
|
||||||
}: StudioProps) {
|
|
||||||
useWindowTitle('Studio Clock');
|
|
||||||
const { hideCards } = useStudioOptions();
|
const { hideCards } = useStudioOptions();
|
||||||
|
|
||||||
// gather option data
|
// gather option data
|
||||||
@@ -51,23 +44,13 @@ export default function Studio({
|
|||||||
<ViewParamsEditor target={OntimeView.StudioClock} viewOptions={studioOptions} />
|
<ViewParamsEditor target={OntimeView.StudioClock} viewOptions={studioOptions} />
|
||||||
|
|
||||||
<div className='project-header'>
|
<div className='project-header'>
|
||||||
{general?.logo && <ViewLogo name={general.logo} className='logo' />}
|
{projectData?.logo && <ViewLogo name={projectData.logo} className='logo' />}
|
||||||
<div className='title'>{general.title}</div>
|
<div className='title'>{projectData.title}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={cx(['studio-contents', hideCards && 'studio-contents--onecol'])}>
|
<div className={cx(['studio-contents', hideCards && 'studio-contents--onecol'])}>
|
||||||
<StudioClock onAir={onAir} clock={time.clock} hideCards={hideCards} />
|
<StudioClock hideCards={hideCards} />
|
||||||
{!hideCards && (
|
{!hideCards && <StudioTimers viewSettings={viewSettings} />}
|
||||||
<StudioTimers
|
|
||||||
eventNow={eventNow}
|
|
||||||
eventNext={eventNext}
|
|
||||||
timerMessage={message.timer.visible ? message.timer.text : ''}
|
|
||||||
secondaryMessage={message.secondary}
|
|
||||||
runtime={runtime}
|
|
||||||
time={time}
|
|
||||||
viewSettings={viewSettings}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
|
import { Playback } from 'ontime-types';
|
||||||
|
|
||||||
import { useIsMobileDevice } from '../../common/hooks/useIsMobileDevice';
|
import { useIsMobileDevice } from '../../common/hooks/useIsMobileDevice';
|
||||||
|
import { useStudioClockSocket } from '../../common/hooks/useSocket';
|
||||||
import { cx } from '../../common/utils/styleUtils';
|
import { cx } from '../../common/utils/styleUtils';
|
||||||
import { formatTime } from '../../common/utils/time';
|
import { formatTime } from '../../common/utils/time';
|
||||||
import SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime';
|
import SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime';
|
||||||
@@ -11,13 +14,13 @@ const activeIndicators = [...Array(12).keys()];
|
|||||||
const secondsIndicators = [...Array(60).keys()];
|
const secondsIndicators = [...Array(60).keys()];
|
||||||
|
|
||||||
interface StudioClockProps {
|
interface StudioClockProps {
|
||||||
onAir: boolean;
|
|
||||||
clock: number;
|
|
||||||
hideCards: boolean;
|
hideCards: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function StudioClock({ onAir, clock, hideCards }: StudioClockProps) {
|
export default function StudioClock({ hideCards }: StudioClockProps) {
|
||||||
const isMobile = useIsMobileDevice();
|
const isMobile = useIsMobileDevice();
|
||||||
|
const { clock, playback } = useStudioClockSocket();
|
||||||
|
const onAir = playback !== Playback.Stop;
|
||||||
|
|
||||||
// if we are on mobile and have to show the cards
|
// if we are on mobile and have to show the cards
|
||||||
if (isMobile && !hideCards) {
|
if (isMobile && !hideCards) {
|
||||||
@@ -55,7 +58,12 @@ export default function StudioClock({ onAir, clock, hideCards }: StudioClockProp
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function StudioClockMobile({ clock, onAir }: Omit<StudioClockProps, 'hideCards'>) {
|
interface StudioClockMobileProps {
|
||||||
|
clock: number;
|
||||||
|
onAir: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function StudioClockMobile({ clock, onAir }: StudioClockMobileProps) {
|
||||||
const displayClock = formatTime(clock);
|
const displayClock = formatTime(clock);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { OntimeEvent, Playback, Runtime, TimerPhase, TimerState, ViewSettings } from 'ontime-types';
|
import { Playback, TimerPhase, ViewSettings } from 'ontime-types';
|
||||||
import { millisToString } from 'ontime-utils';
|
import { millisToString } from 'ontime-utils';
|
||||||
|
|
||||||
import { useAuxTimersTime } from '../../common/hooks/useSocket';
|
import { useAuxTimersTime, useStudioTimersSocket } from '../../common/hooks/useSocket';
|
||||||
import { getOffsetState } from '../../common/utils/offset';
|
import { getOffsetState } from '../../common/utils/offset';
|
||||||
import { cx } from '../../common/utils/styleUtils';
|
import { cx } from '../../common/utils/styleUtils';
|
||||||
import { useTranslation } from '../../translation/TranslationProvider';
|
import { useTranslation } from '../../translation/TranslationProvider';
|
||||||
@@ -12,31 +12,18 @@ import { getFormattedEventData, getFormattedScheduleTimes } from './studioTimers
|
|||||||
import './StudioTimers.scss';
|
import './StudioTimers.scss';
|
||||||
|
|
||||||
interface StudioTimersProps {
|
interface StudioTimersProps {
|
||||||
runtime: Runtime;
|
|
||||||
time: TimerState;
|
|
||||||
eventNow: OntimeEvent | null;
|
|
||||||
eventNext: OntimeEvent | null;
|
|
||||||
timerMessage: string;
|
|
||||||
secondaryMessage: string;
|
|
||||||
viewSettings: ViewSettings;
|
viewSettings: ViewSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function StudioTimers({
|
export default function StudioTimers({ viewSettings }: StudioTimersProps) {
|
||||||
runtime,
|
|
||||||
time,
|
|
||||||
eventNow,
|
|
||||||
eventNext,
|
|
||||||
timerMessage,
|
|
||||||
secondaryMessage,
|
|
||||||
viewSettings,
|
|
||||||
}: StudioTimersProps) {
|
|
||||||
const { getLocalizedString } = useTranslation();
|
const { getLocalizedString } = useTranslation();
|
||||||
|
const { eventNow, eventNext, message, time, runtime } = useStudioTimersSocket();
|
||||||
|
|
||||||
const schedule = getFormattedScheduleTimes(runtime);
|
const schedule = getFormattedScheduleTimes(runtime);
|
||||||
const event = getFormattedEventData(eventNow, time);
|
const event = getFormattedEventData(eventNow, time);
|
||||||
const eventNextTitle = eventNext?.title || '-';
|
const eventNextTitle = eventNext?.title || '-';
|
||||||
const formattedTimerMessage = timerMessage || '-';
|
const formattedTimerMessage = (message.timer.visible && message.timer.text) || '-';
|
||||||
const formattedSecondaryMessage = secondaryMessage || '-';
|
const formattedSecondaryMessage = message.secondary || '-';
|
||||||
|
|
||||||
// gather presentation styles
|
// gather presentation styles
|
||||||
const timerColour = getTimerColour(
|
const timerColour = getTimerColour(
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { ProjectData, Settings, ViewSettings } from 'ontime-types';
|
||||||
|
|
||||||
|
import useProjectData from '../../common/hooks-query/useProjectData';
|
||||||
|
import useSettings from '../../common/hooks-query/useSettings';
|
||||||
|
import useViewSettings from '../../common/hooks-query/useViewSettings';
|
||||||
|
import { useViewOptionsStore } from '../../common/stores/viewOptions';
|
||||||
|
import { aggregateQueryStatus, ViewData } from '../utils/viewLoader.utils';
|
||||||
|
|
||||||
|
export interface StudioData {
|
||||||
|
projectData: ProjectData;
|
||||||
|
isMirrored: boolean;
|
||||||
|
settings: Settings;
|
||||||
|
viewSettings: ViewSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useStudioData(): ViewData<StudioData> {
|
||||||
|
// persisted app state
|
||||||
|
const isMirrored = useViewOptionsStore((state) => state.mirror);
|
||||||
|
|
||||||
|
// HTTP API data
|
||||||
|
const { data: projectData, status: projectDataStatus } = useProjectData();
|
||||||
|
const { data: viewSettings, status: viewSettingsStatus } = useViewSettings();
|
||||||
|
const { data: settings, status: settingsStatus } = useSettings();
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
projectData,
|
||||||
|
isMirrored,
|
||||||
|
settings,
|
||||||
|
viewSettings,
|
||||||
|
},
|
||||||
|
status: aggregateQueryStatus([projectDataStatus, viewSettingsStatus, settingsStatus]),
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user