Compare commits
2 Commits
9cf41dd094
...
ba7b6e4755
Author | SHA1 | Date | |
---|---|---|---|
ba7b6e4755 | |||
3beafab7e1 |
2684
front/pnpm-lock.yaml
generated
2684
front/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,7 @@ import { useSpecificGender } from '@/service/Gender';
|
||||
import { useSpecificTrack } from '@/service/Track';
|
||||
import { DataUrlAccess } from '@/utils/data-url-access';
|
||||
import { isNullOrUndefined } from '@/utils/validator';
|
||||
import { usePageVisibility } from '@/utils/visibleook';
|
||||
|
||||
import { Slider } from './ui/slider';
|
||||
|
||||
@ -89,6 +90,7 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
||||
: ''
|
||||
);
|
||||
}, [dataTrack, setMediaSource]);
|
||||
const { isVisible } = usePageVisibility();
|
||||
const backColor = useColorModeValue('back.100', 'back.800');
|
||||
const configButton = {
|
||||
borderRadius: 'full',
|
||||
@ -201,7 +203,6 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
||||
if (!audioRef || !audioRef.current) {
|
||||
return;
|
||||
}
|
||||
console.log(`onTimeUpdate ${audioRef.current.currentTime}`);
|
||||
setTimeProgress(audioRef.current.currentTime);
|
||||
};
|
||||
const onDurationChange = (event) => {};
|
||||
@ -221,150 +222,154 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
||||
};
|
||||
return (
|
||||
<>
|
||||
{!isNullOrUndefined(trackOffset) && (
|
||||
<Flex
|
||||
position="absolute"
|
||||
height="150px"
|
||||
minHeight="150px"
|
||||
paddingY="5px"
|
||||
paddingX="10px"
|
||||
marginX="15px"
|
||||
bottom={0}
|
||||
//top="calc(100% - 150px)"
|
||||
left={0}
|
||||
right={0}
|
||||
zIndex={1000}
|
||||
borderWidth="1px"
|
||||
borderColor="brand.900"
|
||||
bgColor={backColor}
|
||||
borderTopRadius="10px"
|
||||
direction="column"
|
||||
>
|
||||
<Text
|
||||
alignContent="left"
|
||||
fontSize="20px"
|
||||
fontWeight="bold"
|
||||
userSelect="none"
|
||||
marginRight="auto"
|
||||
overflow="hidden"
|
||||
// noOfLines={1}
|
||||
>
|
||||
{dataTrack?.name ?? '???'}
|
||||
</Text>
|
||||
<Text
|
||||
alignContent="left"
|
||||
fontSize="16px"
|
||||
userSelect="none"
|
||||
marginRight="auto"
|
||||
overflow="hidden"
|
||||
// noOfLines={1}
|
||||
>
|
||||
{dataArtists.map((data) => data.name).join(', ')} /{' '}
|
||||
{dataAlbum && dataAlbum?.name}
|
||||
{dataGender && ` / ${dataGender.name}`}
|
||||
</Text>
|
||||
<Box width="full" paddingX="15px">
|
||||
<Slider
|
||||
defaultValue={[0]}
|
||||
value={[timeProgress]}
|
||||
min={0}
|
||||
max={duration}
|
||||
step={0.1}
|
||||
onValueChange={(e) => onSeek(e.value)}
|
||||
variant="outline"
|
||||
colorPalette="brand"
|
||||
marks={marks()}
|
||||
//focusCapture={false}
|
||||
{isVisible && (
|
||||
<>
|
||||
{!isNullOrUndefined(trackOffset) && (
|
||||
<Flex
|
||||
position="absolute"
|
||||
height="150px"
|
||||
minHeight="150px"
|
||||
paddingY="5px"
|
||||
paddingX="10px"
|
||||
marginX="15px"
|
||||
bottom={0}
|
||||
//top="calc(100% - 150px)"
|
||||
left={0}
|
||||
right={0}
|
||||
zIndex={1000}
|
||||
borderWidth="1px"
|
||||
borderColor="brand.900"
|
||||
bgColor={backColor}
|
||||
borderTopRadius="10px"
|
||||
direction="column"
|
||||
>
|
||||
<SliderTrack
|
||||
bg="brand.200"
|
||||
height="10px"
|
||||
borderRadius="full"
|
||||
></SliderTrack>
|
||||
</Slider>
|
||||
</Box>
|
||||
<Flex>
|
||||
<Text
|
||||
alignContent="left"
|
||||
fontSize="16px"
|
||||
userSelect="none"
|
||||
marginRight="auto"
|
||||
overflow="hidden"
|
||||
// noOfLines={1}
|
||||
>
|
||||
{formatTime(timeProgress)}
|
||||
</Text>
|
||||
<Text alignContent="left" fontSize="16px" userSelect="none">
|
||||
{formatTime(duration)}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Flex gap="5px">
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'Play'}
|
||||
onClick={onPlay}
|
||||
variant="ghost"
|
||||
>
|
||||
{isPlaying ? (
|
||||
<MdPause style={{ width: '100%', height: '100%' }} />
|
||||
) : (
|
||||
<MdPlayArrow style={{ width: '100%', height: '100%' }} />
|
||||
)}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'Stop'}
|
||||
onClick={onStop}
|
||||
variant="ghost"
|
||||
>
|
||||
<MdStop style={{ width: '100%', height: '100%' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'Previous track'}
|
||||
onClick={onNavigatePrevious}
|
||||
marginLeft="auto"
|
||||
variant="ghost"
|
||||
>
|
||||
<MdNavigateBefore
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
/>{' '}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'jump 15sec in past'}
|
||||
onClick={onFastRewind}
|
||||
variant="ghost"
|
||||
>
|
||||
<MdFastRewind style={{ width: '100%', height: '100%' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'jump 15sec in future'}
|
||||
onClick={onFastForward}
|
||||
variant="ghost"
|
||||
>
|
||||
<MdFastForward style={{ width: '100%', height: '100%' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'Next track'}
|
||||
marginRight="auto"
|
||||
onClick={onNavigateNext}
|
||||
variant="ghost"
|
||||
>
|
||||
<MdNavigateNext style={{ width: '100%', height: '100%' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'continue to the end'}
|
||||
onClick={onTypePlay}
|
||||
variant="ghost"
|
||||
>
|
||||
{playModeIcon[playingMode]}
|
||||
</IconButton>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Text
|
||||
alignContent="left"
|
||||
fontSize="20px"
|
||||
fontWeight="bold"
|
||||
userSelect="none"
|
||||
marginRight="auto"
|
||||
overflow="hidden"
|
||||
// noOfLines={1}
|
||||
>
|
||||
{dataTrack?.name ?? '???'}
|
||||
</Text>
|
||||
<Text
|
||||
alignContent="left"
|
||||
fontSize="16px"
|
||||
userSelect="none"
|
||||
marginRight="auto"
|
||||
overflow="hidden"
|
||||
// noOfLines={1}
|
||||
>
|
||||
{dataArtists.map((data) => data.name).join(', ')} /{' '}
|
||||
{dataAlbum && dataAlbum?.name}
|
||||
{dataGender && ` / ${dataGender.name}`}
|
||||
</Text>
|
||||
<Box width="full" paddingX="15px">
|
||||
<Slider
|
||||
defaultValue={[0]}
|
||||
value={[timeProgress]}
|
||||
min={0}
|
||||
max={duration}
|
||||
step={0.1}
|
||||
onValueChange={(e) => onSeek(e.value)}
|
||||
variant="outline"
|
||||
colorPalette="brand"
|
||||
marks={marks()}
|
||||
//focusCapture={false}
|
||||
>
|
||||
<SliderTrack
|
||||
bg="brand.200"
|
||||
height="10px"
|
||||
borderRadius="full"
|
||||
></SliderTrack>
|
||||
</Slider>
|
||||
</Box>
|
||||
<Flex>
|
||||
<Text
|
||||
alignContent="left"
|
||||
fontSize="16px"
|
||||
userSelect="none"
|
||||
marginRight="auto"
|
||||
overflow="hidden"
|
||||
// noOfLines={1}
|
||||
>
|
||||
{formatTime(timeProgress)}
|
||||
</Text>
|
||||
<Text alignContent="left" fontSize="16px" userSelect="none">
|
||||
{formatTime(duration)}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Flex gap="5px">
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'Play'}
|
||||
onClick={onPlay}
|
||||
variant="ghost"
|
||||
>
|
||||
{isPlaying ? (
|
||||
<MdPause style={{ width: '100%', height: '100%' }} />
|
||||
) : (
|
||||
<MdPlayArrow style={{ width: '100%', height: '100%' }} />
|
||||
)}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'Stop'}
|
||||
onClick={onStop}
|
||||
variant="ghost"
|
||||
>
|
||||
<MdStop style={{ width: '100%', height: '100%' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'Previous track'}
|
||||
onClick={onNavigatePrevious}
|
||||
marginLeft="auto"
|
||||
variant="ghost"
|
||||
>
|
||||
<MdNavigateBefore
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
/>{' '}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'jump 15sec in past'}
|
||||
onClick={onFastRewind}
|
||||
variant="ghost"
|
||||
>
|
||||
<MdFastRewind style={{ width: '100%', height: '100%' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'jump 15sec in future'}
|
||||
onClick={onFastForward}
|
||||
variant="ghost"
|
||||
>
|
||||
<MdFastForward style={{ width: '100%', height: '100%' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'Next track'}
|
||||
marginRight="auto"
|
||||
onClick={onNavigateNext}
|
||||
variant="ghost"
|
||||
>
|
||||
<MdNavigateNext style={{ width: '100%', height: '100%' }} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...configButton}
|
||||
aria-label={'continue to the end'}
|
||||
onClick={onTypePlay}
|
||||
variant="ghost"
|
||||
>
|
||||
{playModeIcon[playingMode]}
|
||||
</IconButton>
|
||||
</Flex>
|
||||
</Flex>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
<chakra.audio
|
||||
|
@ -15,6 +15,7 @@ import { HomePage } from '@/scene/home/HomePage';
|
||||
import { SSORoutes } from '@/scene/sso/SSORoutes';
|
||||
import { TrackRoutes } from '@/scene/track/TrackRoutes';
|
||||
import { useHasRight } from '@/service/session';
|
||||
import { usePageVisibility } from '@/utils/visibleook';
|
||||
|
||||
import { AddPage } from './home/AddPage';
|
||||
import { SettingsPage } from './home/SettingsPage';
|
||||
@ -22,6 +23,7 @@ import { OnAirPage } from './onAir/OnAirPage';
|
||||
|
||||
export const AppRoutes = () => {
|
||||
const { isReadable } = useHasRight('USER');
|
||||
const { isVisible } = usePageVisibility();
|
||||
return (
|
||||
<HistoryRouter
|
||||
// @ts-expect-error
|
||||
@ -31,22 +33,27 @@ export const AppRoutes = () => {
|
||||
<Routes>
|
||||
{/* Need to keep it in all case, it is the only way to log-in */}
|
||||
<Route path="sso/*" element={<SSORoutes />} />
|
||||
{isReadable ? (
|
||||
{/* Disable full display to prevent update of GUI when the application is hided */}
|
||||
{isVisible && (
|
||||
<>
|
||||
<Route path="/" element={<Navigate to="home" replace />} />
|
||||
<Route path="home/*" element={<HomePage />} />
|
||||
<Route path="help/*" element={<HelpPage />} />
|
||||
<Route path="settings/*" element={<SettingsPage />} />
|
||||
<Route path="add/*" element={<AddPage />} />
|
||||
<Route path="on-air/*" element={<OnAirPage />} />
|
||||
<Route path="artist/*" element={<ArtistRoutes />} />
|
||||
<Route path="album/*" element={<AlbumRoutes />} />
|
||||
<Route path="gender/*" element={<GenderRoutes />} />
|
||||
<Route path="track/*" element={<TrackRoutes />} />
|
||||
<Route path="*" element={<Error404 />} />
|
||||
{isReadable ? (
|
||||
<>
|
||||
<Route path="/" element={<Navigate to="home" replace />} />
|
||||
<Route path="home/*" element={<HomePage />} />
|
||||
<Route path="help/*" element={<HelpPage />} />
|
||||
<Route path="settings/*" element={<SettingsPage />} />
|
||||
<Route path="add/*" element={<AddPage />} />
|
||||
<Route path="on-air/*" element={<OnAirPage />} />
|
||||
<Route path="artist/*" element={<ArtistRoutes />} />
|
||||
<Route path="album/*" element={<AlbumRoutes />} />
|
||||
<Route path="gender/*" element={<GenderRoutes />} />
|
||||
<Route path="track/*" element={<TrackRoutes />} />
|
||||
<Route path="*" element={<Error404 />} />
|
||||
</>
|
||||
) : (
|
||||
<Route path="*" element={<Error401 />} />
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<Route path="*" element={<Error401 />} />
|
||||
)}
|
||||
</Routes>
|
||||
</HistoryRouter>
|
||||
|
19
front/src/utils/visibleook.tsx
Normal file
19
front/src/utils/visibleook.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export const usePageVisibility = () => {
|
||||
const [isVisible, setIsVisible] = useState(!document.hidden);
|
||||
|
||||
useEffect(() => {
|
||||
const handleVisibilityChange = () => {
|
||||
setIsVisible(!document.hidden);
|
||||
};
|
||||
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return { isVisible };
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user