Compare commits

..

No commits in common. "ba7b6e4755f83d1f99495a03649a783e04668d3e" and "9cf41dd0948e26f981dd5d800e753ee4fa7cb903" have entirely different histories.

4 changed files with 1333 additions and 1698 deletions

2684
front/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,6 @@ 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';
@ -90,7 +89,6 @@ 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',
@ -203,6 +201,7 @@ 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) => {};
@ -222,154 +221,150 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
}; };
return ( return (
<> <>
{isVisible && ( {!isNullOrUndefined(trackOffset) && (
<> <Flex
{!isNullOrUndefined(trackOffset) && ( position="absolute"
<Flex height="150px"
position="absolute" minHeight="150px"
height="150px" paddingY="5px"
minHeight="150px" paddingX="10px"
paddingY="5px" marginX="15px"
paddingX="10px" bottom={0}
marginX="15px" //top="calc(100% - 150px)"
bottom={0} left={0}
//top="calc(100% - 150px)" right={0}
left={0} zIndex={1000}
right={0} borderWidth="1px"
zIndex={1000} borderColor="brand.900"
borderWidth="1px" bgColor={backColor}
borderColor="brand.900" borderTopRadius="10px"
bgColor={backColor} direction="column"
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}
> >
<Text <SliderTrack
alignContent="left" bg="brand.200"
fontSize="20px" height="10px"
fontWeight="bold" borderRadius="full"
userSelect="none" ></SliderTrack>
marginRight="auto" </Slider>
overflow="hidden" </Box>
// noOfLines={1} <Flex>
> <Text
{dataTrack?.name ?? '???'} alignContent="left"
</Text> fontSize="16px"
<Text userSelect="none"
alignContent="left" marginRight="auto"
fontSize="16px" overflow="hidden"
userSelect="none" // noOfLines={1}
marginRight="auto" >
overflow="hidden" {formatTime(timeProgress)}
// noOfLines={1} </Text>
> <Text alignContent="left" fontSize="16px" userSelect="none">
{dataArtists.map((data) => data.name).join(', ')} /{' '} {formatTime(duration)}
{dataAlbum && dataAlbum?.name} </Text>
{dataGender && ` / ${dataGender.name}`} </Flex>
</Text> <Flex gap="5px">
<Box width="full" paddingX="15px"> <IconButton
<Slider {...configButton}
defaultValue={[0]} aria-label={'Play'}
value={[timeProgress]} onClick={onPlay}
min={0} variant="ghost"
max={duration} >
step={0.1} {isPlaying ? (
onValueChange={(e) => onSeek(e.value)} <MdPause style={{ width: '100%', height: '100%' }} />
variant="outline" ) : (
colorPalette="brand" <MdPlayArrow style={{ width: '100%', height: '100%' }} />
marks={marks()} )}
//focusCapture={false} </IconButton>
> <IconButton
<SliderTrack {...configButton}
bg="brand.200" aria-label={'Stop'}
height="10px" onClick={onStop}
borderRadius="full" variant="ghost"
></SliderTrack> >
</Slider> <MdStop style={{ width: '100%', height: '100%' }} />
</Box> </IconButton>
<Flex> <IconButton
<Text {...configButton}
alignContent="left" aria-label={'Previous track'}
fontSize="16px" onClick={onNavigatePrevious}
userSelect="none" marginLeft="auto"
marginRight="auto" variant="ghost"
overflow="hidden" >
// noOfLines={1} <MdNavigateBefore
> style={{ width: '100%', height: '100%' }}
{formatTime(timeProgress)} />{' '}
</Text> </IconButton>
<Text alignContent="left" fontSize="16px" userSelect="none"> <IconButton
{formatTime(duration)} {...configButton}
</Text> aria-label={'jump 15sec in past'}
</Flex> onClick={onFastRewind}
<Flex gap="5px"> variant="ghost"
<IconButton >
{...configButton} <MdFastRewind style={{ width: '100%', height: '100%' }} />
aria-label={'Play'} </IconButton>
onClick={onPlay} <IconButton
variant="ghost" {...configButton}
> aria-label={'jump 15sec in future'}
{isPlaying ? ( onClick={onFastForward}
<MdPause style={{ width: '100%', height: '100%' }} /> variant="ghost"
) : ( >
<MdPlayArrow style={{ width: '100%', height: '100%' }} /> <MdFastForward style={{ width: '100%', height: '100%' }} />
)} </IconButton>
</IconButton> <IconButton
<IconButton {...configButton}
{...configButton} aria-label={'Next track'}
aria-label={'Stop'} marginRight="auto"
onClick={onStop} onClick={onNavigateNext}
variant="ghost" variant="ghost"
> >
<MdStop style={{ width: '100%', height: '100%' }} /> <MdNavigateNext style={{ width: '100%', height: '100%' }} />
</IconButton> </IconButton>
<IconButton <IconButton
{...configButton} {...configButton}
aria-label={'Previous track'} aria-label={'continue to the end'}
onClick={onNavigatePrevious} onClick={onTypePlay}
marginLeft="auto" variant="ghost"
variant="ghost" >
> {playModeIcon[playingMode]}
<MdNavigateBefore </IconButton>
style={{ width: '100%', height: '100%' }} </Flex>
/>{' '} </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

View File

@ -15,7 +15,6 @@ 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';
@ -23,7 +22,6 @@ 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
@ -33,27 +31,22 @@ 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 />} />
{/* Disable full display to prevent update of GUI when the application is hided */} {isReadable ? (
{isVisible && (
<> <>
{isReadable ? ( <Route path="/" element={<Navigate to="home" replace />} />
<> <Route path="home/*" element={<HomePage />} />
<Route path="/" element={<Navigate to="home" replace />} /> <Route path="help/*" element={<HelpPage />} />
<Route path="home/*" element={<HomePage />} /> <Route path="settings/*" element={<SettingsPage />} />
<Route path="help/*" element={<HelpPage />} /> <Route path="add/*" element={<AddPage />} />
<Route path="settings/*" element={<SettingsPage />} /> <Route path="on-air/*" element={<OnAirPage />} />
<Route path="add/*" element={<AddPage />} /> <Route path="artist/*" element={<ArtistRoutes />} />
<Route path="on-air/*" element={<OnAirPage />} /> <Route path="album/*" element={<AlbumRoutes />} />
<Route path="artist/*" element={<ArtistRoutes />} /> <Route path="gender/*" element={<GenderRoutes />} />
<Route path="album/*" element={<AlbumRoutes />} /> <Route path="track/*" element={<TrackRoutes />} />
<Route path="gender/*" element={<GenderRoutes />} /> <Route path="*" element={<Error404 />} />
<Route path="track/*" element={<TrackRoutes />} />
<Route path="*" element={<Error404 />} />
</>
) : (
<Route path="*" element={<Error401 />} />
)}
</> </>
) : (
<Route path="*" element={<Error401 />} />
)} )}
</Routes> </Routes>
</HistoryRouter> </HistoryRouter>

View File

@ -1,19 +0,0 @@
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 };
};