mirror of
https://github.com/cpvalente/ontime.git
synced 2026-07-26 10:38:55 +00:00
refactor: editor responsive navigation
This commit is contained in:
committed by
Carlos Valente
parent
cff73a65a5
commit
b991627cb7
@@ -9,10 +9,11 @@ import useViewEditor from './useViewEditor';
|
||||
|
||||
interface ViewNavigationMenuProps {
|
||||
isLockable?: boolean;
|
||||
supressSettings?: boolean;
|
||||
}
|
||||
|
||||
export default memo(ViewNavigationMenu);
|
||||
function ViewNavigationMenu({ isLockable }: ViewNavigationMenuProps) {
|
||||
function ViewNavigationMenu({ isLockable, supressSettings }: ViewNavigationMenuProps) {
|
||||
const { isOpen: isMenuOpen, onOpen: onMenuOpen, onClose: onMenuClose } = useDisclosure();
|
||||
const { showEditFormDrawer, isViewLocked } = useViewEditor({ isLockable });
|
||||
|
||||
@@ -30,7 +31,7 @@ function ViewNavigationMenu({ isLockable }: ViewNavigationMenuProps) {
|
||||
[
|
||||
'mod + ,',
|
||||
() => {
|
||||
if (isViewLocked) return;
|
||||
if (isViewLocked || supressSettings) return;
|
||||
showEditFormDrawer();
|
||||
},
|
||||
{ preventDefault: true },
|
||||
@@ -43,7 +44,10 @@ function ViewNavigationMenu({ isLockable }: ViewNavigationMenuProps) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<FloatingNavigation toggleMenu={toggleMenu} toggleSettings={showEditFormDrawer} />
|
||||
<FloatingNavigation
|
||||
toggleMenu={toggleMenu}
|
||||
toggleSettings={supressSettings ? undefined : () => showEditFormDrawer()}
|
||||
/>
|
||||
<NavigationMenu isOpen={isMenuOpen} onClose={onMenuClose} />
|
||||
</>
|
||||
);
|
||||
|
||||
+3
-3
@@ -1,14 +1,14 @@
|
||||
import { IoLockClosedOutline } from 'react-icons/io5';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useViewportSize } from '@mantine/hooks';
|
||||
|
||||
import { useIsSmallDevice } from '../../../hooks/useIsSmallDevice';
|
||||
import NavigationMenuItem from '../navigation-menu-item/NavigationMenuItem';
|
||||
|
||||
export default function EditorNavigation() {
|
||||
const { width } = useViewportSize();
|
||||
const navigate = useNavigate();
|
||||
const isSmallDevide = useIsSmallDevice();
|
||||
|
||||
if (width > 1440) {
|
||||
if (!isSmallDevide) {
|
||||
return (
|
||||
<NavigationMenuItem active={location.pathname === '/editor'} onClick={() => navigate('/editor')}>
|
||||
<IoLockClosedOutline />
|
||||
|
||||
+12
-10
@@ -9,7 +9,7 @@ import style from './FloatingNavigation.module.scss';
|
||||
|
||||
interface FloatingNavigationProps {
|
||||
toggleMenu: () => void;
|
||||
toggleSettings: () => void;
|
||||
toggleSettings?: () => void;
|
||||
}
|
||||
|
||||
export default function FloatingNavigation({ toggleMenu, toggleSettings }: FloatingNavigationProps) {
|
||||
@@ -29,15 +29,17 @@ export default function FloatingNavigation({ toggleMenu, toggleSettings }: Float
|
||||
>
|
||||
<IoApps />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
variant='subtle-white'
|
||||
size='xlarge'
|
||||
onClick={toggleSettings}
|
||||
aria-label='toggle settings'
|
||||
data-testid='navigation__toggle-settings'
|
||||
>
|
||||
<IoSettingsOutline />
|
||||
</IconButton>
|
||||
{toggleSettings && (
|
||||
<IconButton
|
||||
variant='subtle-white'
|
||||
size='xlarge'
|
||||
onClick={toggleSettings}
|
||||
aria-label='toggle settings'
|
||||
data-testid='navigation__toggle-settings'
|
||||
>
|
||||
<IoSettingsOutline />
|
||||
</IconButton>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useOs, useViewportSize } from '@mantine/hooks';
|
||||
|
||||
export function useIsMobile(): boolean {
|
||||
const { width } = useViewportSize();
|
||||
const os = useOs();
|
||||
|
||||
return useMemo(() => (os === 'ios' || os === 'android') && width < 800, [width, os]);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useOs, useViewportSize } from '@mantine/hooks';
|
||||
|
||||
export function useIsSmallDevice(): boolean {
|
||||
const { width } = useViewportSize();
|
||||
const os = useOs();
|
||||
|
||||
return useMemo(() => (os === 'ios' || os === 'android') && width < 1300, [width, os]);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useViewportSize } from '@mantine/hooks';
|
||||
|
||||
export function useIsSmallScreen(): boolean {
|
||||
const { width } = useViewportSize();
|
||||
|
||||
return useMemo(() => width < 1300, [width]);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import { memo } from 'react';
|
||||
|
||||
import ErrorBoundary from '../../../common/components/error-boundary/ErrorBoundary';
|
||||
import ViewNavigationMenu from '../../../common/components/navigation-menu/ViewNavigationMenu';
|
||||
import ProtectRoute from '../../../common/components/protect-route/ProtectRoute';
|
||||
import { handleLinks } from '../../../common/utils/linkUtils';
|
||||
import { cx } from '../../../common/utils/styleUtils';
|
||||
import { Corner } from '../../editors/editor-utils/EditorUtils';
|
||||
@@ -9,20 +11,23 @@ import MessageControl from './MessageControl';
|
||||
|
||||
import style from '../../editors/Editor.module.scss';
|
||||
|
||||
const MessageControlExport = () => {
|
||||
export default memo(MessageControlExport);
|
||||
function MessageControlExport() {
|
||||
const isExtracted = window.location.pathname.includes('/messagecontrol');
|
||||
const classes = cx([style.content, style.contentColumnLayout]);
|
||||
|
||||
return (
|
||||
<div className={style.messages} data-testid='panel-messages-control'>
|
||||
{!isExtracted && <Corner onClick={(event) => handleLinks('messagecontrol', event)} />}
|
||||
<div className={classes}>
|
||||
<ErrorBoundary>
|
||||
<MessageControl />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
<ProtectRoute permission='editor'>
|
||||
<div className={style.messages} data-testid='panel-messages-control'>
|
||||
{!isExtracted && <Corner onClick={(event) => handleLinks('messagecontrol', event)} />}
|
||||
{isExtracted && <ViewNavigationMenu supressSettings />}
|
||||
|
||||
export default memo(MessageControlExport);
|
||||
<div className={classes}>
|
||||
<ErrorBoundary>
|
||||
<MessageControl />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</div>
|
||||
</ProtectRoute>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { memo } from 'react';
|
||||
|
||||
import ErrorBoundary from '../../../common/components/error-boundary/ErrorBoundary';
|
||||
import ViewNavigationMenu from '../../../common/components/navigation-menu/ViewNavigationMenu';
|
||||
import ProtectRoute from '../../../common/components/protect-route/ProtectRoute';
|
||||
import { handleLinks } from '../../../common/utils/linkUtils';
|
||||
import { Corner } from '../../editors/editor-utils/EditorUtils';
|
||||
|
||||
@@ -8,18 +10,22 @@ import PlaybackControl from './PlaybackControl';
|
||||
|
||||
import style from '../../editors/Editor.module.scss';
|
||||
|
||||
const TimerControlExport = () => {
|
||||
const isExtracted = window.location.pathname.includes('/timercontrol');
|
||||
return (
|
||||
<div className={style.playback} data-testid='panel-timer-control'>
|
||||
{!isExtracted && <Corner onClick={(event) => handleLinks('timercontrol', event)} />}
|
||||
<div className={style.content}>
|
||||
<ErrorBoundary>
|
||||
<PlaybackControl />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(TimerControlExport);
|
||||
function TimerControlExport() {
|
||||
const isExtracted = window.location.pathname.includes('/timercontrol');
|
||||
|
||||
return (
|
||||
<ProtectRoute permission='editor'>
|
||||
<div className={style.playback} data-testid='panel-timer-control'>
|
||||
{!isExtracted && <Corner onClick={(event) => handleLinks('timercontrol', event)} />}
|
||||
{isExtracted && <ViewNavigationMenu supressSettings />}
|
||||
|
||||
<div className={style.content}>
|
||||
<ErrorBoundary>
|
||||
<PlaybackControl />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</div>
|
||||
</ProtectRoute>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ import { memo } from 'react';
|
||||
|
||||
import { ContextMenu } from '../../common/components/context-menu/ContextMenu';
|
||||
import ErrorBoundary from '../../common/components/error-boundary/ErrorBoundary';
|
||||
import ViewNavigationMenu from '../../common/components/navigation-menu/ViewNavigationMenu';
|
||||
import ProtectRoute from '../../common/components/protect-route/ProtectRoute';
|
||||
import { useIsSmallDevice } from '../../common/hooks/useIsSmallDevice';
|
||||
import { useAppMode } from '../../common/stores/appModeStore';
|
||||
import { handleLinks } from '../../common/utils/linkUtils';
|
||||
import { cx } from '../../common/utils/styleUtils';
|
||||
@@ -18,30 +21,50 @@ export default memo(RundownExport);
|
||||
function RundownExport() {
|
||||
const isExtracted = window.location.pathname.includes('/rundown');
|
||||
const appMode = useAppMode((state) => state.mode);
|
||||
const hideSideBar = isExtracted && appMode === 'run';
|
||||
const isSmallDevice = useIsSmallDevice();
|
||||
|
||||
const classes = cx([style.rundownExport, isExtracted && style.extracted]);
|
||||
|
||||
return (
|
||||
<div className={classes} data-testid='panel-rundown'>
|
||||
<FinderPlacement />
|
||||
<div className={style.rundown}>
|
||||
<div className={style.list}>
|
||||
<ErrorBoundary>
|
||||
{!isExtracted && <Corner onClick={(event) => handleLinks('rundown', event)} />}
|
||||
<ContextMenu>
|
||||
<RundownWrapper />
|
||||
</ContextMenu>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
{!hideSideBar && (
|
||||
<div className={style.side}>
|
||||
if (isSmallDevice && isExtracted) {
|
||||
return (
|
||||
<ProtectRoute permission='editor'>
|
||||
<div className={cx([style.rundownExport, style.extracted])} data-testid='panel-rundown'>
|
||||
<FinderPlacement />
|
||||
<ViewNavigationMenu supressSettings />
|
||||
<div className={style.content}>
|
||||
<ErrorBoundary>
|
||||
<RundownEventEditor />
|
||||
<ContextMenu>
|
||||
<RundownWrapper />
|
||||
</ContextMenu>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</ProtectRoute>
|
||||
);
|
||||
}
|
||||
|
||||
const hideSideBar = isExtracted && appMode === 'run';
|
||||
|
||||
return (
|
||||
<ProtectRoute permission='editor'>
|
||||
<div className={cx([style.rundownExport, isExtracted && style.extracted])} data-testid='panel-rundown'>
|
||||
<FinderPlacement />
|
||||
<div className={style.rundown}>
|
||||
<div className={style.list}>
|
||||
<ErrorBoundary>
|
||||
<Corner onClick={(event) => handleLinks('rundown', event)} />
|
||||
<ContextMenu>
|
||||
<RundownWrapper />
|
||||
</ContextMenu>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
{!hideSideBar && (
|
||||
<div className={style.side}>
|
||||
<ErrorBoundary>
|
||||
<RundownEventEditor />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ProtectRoute>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useViewportSize } from '@mantine/hooks';
|
||||
|
||||
import { useIsMobile } from '../../common/hooks/useIsMobile';
|
||||
import { cx } from '../../common/utils/styleUtils';
|
||||
import { formatTime } from '../../common/utils/time';
|
||||
import SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime';
|
||||
@@ -18,10 +17,10 @@ interface StudioClockProps {
|
||||
}
|
||||
|
||||
export default function StudioClock({ onAir, clock, hideCards }: StudioClockProps) {
|
||||
const { width } = useViewportSize();
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
// if we are on mobile and have to show the cards
|
||||
if (width < 800 && !hideCards) {
|
||||
if (isMobile && !hideCards) {
|
||||
return <StudioClockMobile clock={clock} onAir={onAir} />;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user