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 { useSpecificTrack } from '@/service/Track';
|
||||||
import { DataUrlAccess } from '@/utils/data-url-access';
|
import { DataUrlAccess } from '@/utils/data-url-access';
|
||||||
import { isNullOrUndefined } from '@/utils/validator';
|
import { isNullOrUndefined } from '@/utils/validator';
|
||||||
|
import { usePageVisibility } from '@/utils/visibleook';
|
||||||
|
|
||||||
import { Slider } from './ui/slider';
|
import { Slider } from './ui/slider';
|
||||||
|
|
||||||
@ -89,6 +90,7 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
|||||||
: ''
|
: ''
|
||||||
);
|
);
|
||||||
}, [dataTrack, setMediaSource]);
|
}, [dataTrack, setMediaSource]);
|
||||||
|
const { isVisible } = usePageVisibility();
|
||||||
const backColor = useColorModeValue('back.100', 'back.800');
|
const backColor = useColorModeValue('back.100', 'back.800');
|
||||||
const configButton = {
|
const configButton = {
|
||||||
borderRadius: 'full',
|
borderRadius: 'full',
|
||||||
@ -201,7 +203,6 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
|||||||
if (!audioRef || !audioRef.current) {
|
if (!audioRef || !audioRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(`onTimeUpdate ${audioRef.current.currentTime}`);
|
|
||||||
setTimeProgress(audioRef.current.currentTime);
|
setTimeProgress(audioRef.current.currentTime);
|
||||||
};
|
};
|
||||||
const onDurationChange = (event) => {};
|
const onDurationChange = (event) => {};
|
||||||
@ -221,150 +222,154 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!isNullOrUndefined(trackOffset) && (
|
{isVisible && (
|
||||||
<Flex
|
<>
|
||||||
position="absolute"
|
{!isNullOrUndefined(trackOffset) && (
|
||||||
height="150px"
|
<Flex
|
||||||
minHeight="150px"
|
position="absolute"
|
||||||
paddingY="5px"
|
height="150px"
|
||||||
paddingX="10px"
|
minHeight="150px"
|
||||||
marginX="15px"
|
paddingY="5px"
|
||||||
bottom={0}
|
paddingX="10px"
|
||||||
//top="calc(100% - 150px)"
|
marginX="15px"
|
||||||
left={0}
|
bottom={0}
|
||||||
right={0}
|
//top="calc(100% - 150px)"
|
||||||
zIndex={1000}
|
left={0}
|
||||||
borderWidth="1px"
|
right={0}
|
||||||
borderColor="brand.900"
|
zIndex={1000}
|
||||||
bgColor={backColor}
|
borderWidth="1px"
|
||||||
borderTopRadius="10px"
|
borderColor="brand.900"
|
||||||
direction="column"
|
bgColor={backColor}
|
||||||
>
|
borderTopRadius="10px"
|
||||||
<Text
|
direction="column"
|
||||||
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
|
<Text
|
||||||
bg="brand.200"
|
alignContent="left"
|
||||||
height="10px"
|
fontSize="20px"
|
||||||
borderRadius="full"
|
fontWeight="bold"
|
||||||
></SliderTrack>
|
userSelect="none"
|
||||||
</Slider>
|
marginRight="auto"
|
||||||
</Box>
|
overflow="hidden"
|
||||||
<Flex>
|
// noOfLines={1}
|
||||||
<Text
|
>
|
||||||
alignContent="left"
|
{dataTrack?.name ?? '???'}
|
||||||
fontSize="16px"
|
</Text>
|
||||||
userSelect="none"
|
<Text
|
||||||
marginRight="auto"
|
alignContent="left"
|
||||||
overflow="hidden"
|
fontSize="16px"
|
||||||
// noOfLines={1}
|
userSelect="none"
|
||||||
>
|
marginRight="auto"
|
||||||
{formatTime(timeProgress)}
|
overflow="hidden"
|
||||||
</Text>
|
// noOfLines={1}
|
||||||
<Text alignContent="left" fontSize="16px" userSelect="none">
|
>
|
||||||
{formatTime(duration)}
|
{dataArtists.map((data) => data.name).join(', ')} /{' '}
|
||||||
</Text>
|
{dataAlbum && dataAlbum?.name}
|
||||||
</Flex>
|
{dataGender && ` / ${dataGender.name}`}
|
||||||
<Flex gap="5px">
|
</Text>
|
||||||
<IconButton
|
<Box width="full" paddingX="15px">
|
||||||
{...configButton}
|
<Slider
|
||||||
aria-label={'Play'}
|
defaultValue={[0]}
|
||||||
onClick={onPlay}
|
value={[timeProgress]}
|
||||||
variant="ghost"
|
min={0}
|
||||||
>
|
max={duration}
|
||||||
{isPlaying ? (
|
step={0.1}
|
||||||
<MdPause style={{ width: '100%', height: '100%' }} />
|
onValueChange={(e) => onSeek(e.value)}
|
||||||
) : (
|
variant="outline"
|
||||||
<MdPlayArrow style={{ width: '100%', height: '100%' }} />
|
colorPalette="brand"
|
||||||
)}
|
marks={marks()}
|
||||||
</IconButton>
|
//focusCapture={false}
|
||||||
<IconButton
|
>
|
||||||
{...configButton}
|
<SliderTrack
|
||||||
aria-label={'Stop'}
|
bg="brand.200"
|
||||||
onClick={onStop}
|
height="10px"
|
||||||
variant="ghost"
|
borderRadius="full"
|
||||||
>
|
></SliderTrack>
|
||||||
<MdStop style={{ width: '100%', height: '100%' }} />
|
</Slider>
|
||||||
</IconButton>
|
</Box>
|
||||||
<IconButton
|
<Flex>
|
||||||
{...configButton}
|
<Text
|
||||||
aria-label={'Previous track'}
|
alignContent="left"
|
||||||
onClick={onNavigatePrevious}
|
fontSize="16px"
|
||||||
marginLeft="auto"
|
userSelect="none"
|
||||||
variant="ghost"
|
marginRight="auto"
|
||||||
>
|
overflow="hidden"
|
||||||
<MdNavigateBefore
|
// noOfLines={1}
|
||||||
style={{ width: '100%', height: '100%' }}
|
>
|
||||||
/>{' '}
|
{formatTime(timeProgress)}
|
||||||
</IconButton>
|
</Text>
|
||||||
<IconButton
|
<Text alignContent="left" fontSize="16px" userSelect="none">
|
||||||
{...configButton}
|
{formatTime(duration)}
|
||||||
aria-label={'jump 15sec in past'}
|
</Text>
|
||||||
onClick={onFastRewind}
|
</Flex>
|
||||||
variant="ghost"
|
<Flex gap="5px">
|
||||||
>
|
<IconButton
|
||||||
<MdFastRewind style={{ width: '100%', height: '100%' }} />
|
{...configButton}
|
||||||
</IconButton>
|
aria-label={'Play'}
|
||||||
<IconButton
|
onClick={onPlay}
|
||||||
{...configButton}
|
variant="ghost"
|
||||||
aria-label={'jump 15sec in future'}
|
>
|
||||||
onClick={onFastForward}
|
{isPlaying ? (
|
||||||
variant="ghost"
|
<MdPause style={{ width: '100%', height: '100%' }} />
|
||||||
>
|
) : (
|
||||||
<MdFastForward style={{ width: '100%', height: '100%' }} />
|
<MdPlayArrow style={{ width: '100%', height: '100%' }} />
|
||||||
</IconButton>
|
)}
|
||||||
<IconButton
|
</IconButton>
|
||||||
{...configButton}
|
<IconButton
|
||||||
aria-label={'Next track'}
|
{...configButton}
|
||||||
marginRight="auto"
|
aria-label={'Stop'}
|
||||||
onClick={onNavigateNext}
|
onClick={onStop}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
>
|
>
|
||||||
<MdNavigateNext style={{ width: '100%', height: '100%' }} />
|
<MdStop style={{ width: '100%', height: '100%' }} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
{...configButton}
|
{...configButton}
|
||||||
aria-label={'continue to the end'}
|
aria-label={'Previous track'}
|
||||||
onClick={onTypePlay}
|
onClick={onNavigatePrevious}
|
||||||
variant="ghost"
|
marginLeft="auto"
|
||||||
>
|
variant="ghost"
|
||||||
{playModeIcon[playingMode]}
|
>
|
||||||
</IconButton>
|
<MdNavigateBefore
|
||||||
</Flex>
|
style={{ width: '100%', height: '100%' }}
|
||||||
</Flex>
|
/>{' '}
|
||||||
|
</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
|
<chakra.audio
|
||||||
|
@ -15,6 +15,7 @@ import { HomePage } from '@/scene/home/HomePage';
|
|||||||
import { SSORoutes } from '@/scene/sso/SSORoutes';
|
import { SSORoutes } from '@/scene/sso/SSORoutes';
|
||||||
import { TrackRoutes } from '@/scene/track/TrackRoutes';
|
import { TrackRoutes } from '@/scene/track/TrackRoutes';
|
||||||
import { useHasRight } from '@/service/session';
|
import { useHasRight } from '@/service/session';
|
||||||
|
import { usePageVisibility } from '@/utils/visibleook';
|
||||||
|
|
||||||
import { AddPage } from './home/AddPage';
|
import { AddPage } from './home/AddPage';
|
||||||
import { SettingsPage } from './home/SettingsPage';
|
import { SettingsPage } from './home/SettingsPage';
|
||||||
@ -22,6 +23,7 @@ import { OnAirPage } from './onAir/OnAirPage';
|
|||||||
|
|
||||||
export const AppRoutes = () => {
|
export const AppRoutes = () => {
|
||||||
const { isReadable } = useHasRight('USER');
|
const { isReadable } = useHasRight('USER');
|
||||||
|
const { isVisible } = usePageVisibility();
|
||||||
return (
|
return (
|
||||||
<HistoryRouter
|
<HistoryRouter
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@ -31,22 +33,27 @@ export const AppRoutes = () => {
|
|||||||
<Routes>
|
<Routes>
|
||||||
{/* Need to keep it in all case, it is the only way to log-in */}
|
{/* Need to keep it in all case, it is the only way to log-in */}
|
||||||
<Route path="sso/*" element={<SSORoutes />} />
|
<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 />} />
|
{isReadable ? (
|
||||||
<Route path="home/*" element={<HomePage />} />
|
<>
|
||||||
<Route path="help/*" element={<HelpPage />} />
|
<Route path="/" element={<Navigate to="home" replace />} />
|
||||||
<Route path="settings/*" element={<SettingsPage />} />
|
<Route path="home/*" element={<HomePage />} />
|
||||||
<Route path="add/*" element={<AddPage />} />
|
<Route path="help/*" element={<HelpPage />} />
|
||||||
<Route path="on-air/*" element={<OnAirPage />} />
|
<Route path="settings/*" element={<SettingsPage />} />
|
||||||
<Route path="artist/*" element={<ArtistRoutes />} />
|
<Route path="add/*" element={<AddPage />} />
|
||||||
<Route path="album/*" element={<AlbumRoutes />} />
|
<Route path="on-air/*" element={<OnAirPage />} />
|
||||||
<Route path="gender/*" element={<GenderRoutes />} />
|
<Route path="artist/*" element={<ArtistRoutes />} />
|
||||||
<Route path="track/*" element={<TrackRoutes />} />
|
<Route path="album/*" element={<AlbumRoutes />} />
|
||||||
<Route path="*" element={<Error404 />} />
|
<Route path="gender/*" element={<GenderRoutes />} />
|
||||||
|
<Route path="track/*" element={<TrackRoutes />} />
|
||||||
|
<Route path="*" element={<Error404 />} />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Route path="*" element={<Error401 />} />
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
|
||||||
<Route path="*" element={<Error401 />} />
|
|
||||||
)}
|
)}
|
||||||
</Routes>
|
</Routes>
|
||||||
</HistoryRouter>
|
</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