Adjust lyrics styling / animations

This commit is contained in:
jeffvli 2023-06-03 18:03:32 -07:00 committed by Jeff
parent 7cd2077dcd
commit 5dd860735d
5 changed files with 47 additions and 28 deletions

View file

@ -7,16 +7,20 @@ interface LyricLineProps extends ComponentPropsWithoutRef<'div'> {
}
const StyledText = styled(TextTitle)`
font-size: 2rem;
color: var(--main-fg);
font-weight: 100;
line-height: 3.5rem;
font-size: 2vmax;
line-height: 3.5vmax;
opacity: 0.5;
&.active,
&.credit {
font-size: 2.5rem;
&.active {
font-weight: 800;
line-height: 4rem;
font-size: 2.5vmax;
line-height: 4vmax;
opacity: 1;
}
transition: opacity 0.3s ease-in-out, font-size 0.3s ease-in-out;
`;
export const LyricLine = ({ text, ...props }: LyricLineProps) => {

View file

@ -1,16 +1,15 @@
import { useEffect, useRef, useState } from 'react';
import { Center, Group } from '@mantine/core';
import isElectron from 'is-electron';
import { ErrorBoundary } from 'react-error-boundary';
import { ErrorFallback } from '/@/renderer/features/action-required';
import { getServerById, useCurrentSong } from '/@/renderer/store';
import { SynchronizedLyrics } from './synchronized-lyrics';
import { UnsynchronizedLyrics } from '/@/renderer/features/lyrics/unsynchronized-lyrics';
import { LyricLine } from '/@/renderer/features/lyrics/lyric-line';
import { Center, Group } from '@mantine/core';
import { RiInformationFill } from 'react-icons/ri';
import { TextTitle } from '/@/renderer/components';
import { LyricsResponse, SynchronizedLyricsArray } from '/@/renderer/api/types';
import { useSongLyrics } from '/@/renderer/features/lyrics/queries/lyric-query';
import { SynchronizedLyrics } from './synchronized-lyrics';
const lyrics = isElectron() ? window.electron.lyrics : null;
@ -120,18 +119,17 @@ export const Lyrics = () => {
</Group>
</Center>
)}
{source && (
<LyricLine
key="provided-by"
className="credit"
text={`Provided by: ${source}`}
/>
)}
{songLyrics &&
(Array.isArray(songLyrics) ? (
<SynchronizedLyrics lyrics={songLyrics} />
<SynchronizedLyrics
lyrics={songLyrics}
source={source}
/>
) : (
<UnsynchronizedLyrics lyrics={songLyrics} />
<UnsynchronizedLyrics
lyrics={songLyrics}
source={source}
/>
))}
</ErrorBoundary>
);

View file

@ -11,14 +11,21 @@ import { LyricLine } from '/@/renderer/features/lyrics/lyric-line';
import isElectron from 'is-electron';
import { PlayersRef } from '/@/renderer/features/player/ref/players-ref';
import { SynchronizedLyricsArray } from '/@/renderer/api/types';
import styled from 'styled-components';
import { Text } from '/@/renderer/components';
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
const SynchronizedLyricsContainer = styled.div`
padding: 3rem 0 10rem;
`;
interface SynchronizedLyricsProps {
lyrics: SynchronizedLyricsArray;
source: string | null;
}
export const SynchronizedLyrics = ({ lyrics }: SynchronizedLyricsProps) => {
export const SynchronizedLyrics = ({ lyrics, source }: SynchronizedLyricsProps) => {
const playersRef = PlayersRef;
const status = useCurrentStatus();
const playerType = usePlayerType();
@ -203,7 +210,8 @@ export const SynchronizedLyrics = ({ lyrics }: SynchronizedLyricsProps) => {
}, []);
return (
<div className="synchronized-lyrics">
<SynchronizedLyricsContainer className="synchronized-lyrics">
{source && <Text $noSelect>Lyrics provided by: {source}</Text>}
{lyrics.map(([, text], idx) => (
<LyricLine
key={idx}
@ -211,6 +219,6 @@ export const SynchronizedLyrics = ({ lyrics }: SynchronizedLyricsProps) => {
text={text}
/>
))}
</div>
</SynchronizedLyricsContainer>
);
};

View file

@ -1,17 +1,20 @@
import { useMemo } from 'react';
import { Text } from '/@/renderer/components';
import { LyricLine } from '/@/renderer/features/lyrics/lyric-line';
interface UnsynchronizedLyricsProps {
lyrics: string;
source: string | null;
}
export const UnsynchronizedLyrics = ({ lyrics }: UnsynchronizedLyricsProps) => {
export const UnsynchronizedLyrics = ({ lyrics, source }: UnsynchronizedLyricsProps) => {
const lines = useMemo(() => {
return lyrics.split('\n');
}, [lyrics]);
return (
<div>
<div className="unsynchronized-lyrics">
{source && <Text $noSelect>Lyrics provided by: {source}</Text>}
{lines.map((text, idx) => (
<LyricLine
key={idx}

View file

@ -3,7 +3,7 @@ import { motion } from 'framer-motion';
import { HiOutlineQueueList } from 'react-icons/hi2';
import { RiFileMusicLine, RiFileTextLine, RiInformationFill } from 'react-icons/ri';
import styled from 'styled-components';
import { Button, TextTitle } from '/@/renderer/components';
import { Button, ScrollArea, TextTitle } from '/@/renderer/components';
import { PlayQueue } from '/@/renderer/features/now-playing';
import {
useFullScreenPlayerStore,
@ -27,10 +27,16 @@ const QueueContainer = styled.div`
}
`;
const LyricsContainer = styled.div`
height: 100%;
overflow: scroll;
const LyricsContainer = styled(ScrollArea)`
text-align: center;
mask-image: linear-gradient(
180deg,
transparent 5%,
rgba(0, 0, 0, 100%) 20%,
rgba(0, 0, 0, 100%) 85%,
transparent 95%
);
`;
const ActiveTabIndicator = styled(motion.div)`
@ -118,7 +124,7 @@ export const FullScreenPlayerQueue = () => {
</Group>
</Center>
) : activeTab === 'lyrics' ? (
<LyricsContainer>
<LyricsContainer scrollHideDelay={0}>
<Lyrics />
</LyricsContainer>
) : null}