Add additional lyrics customizability options (#146)

This commit is contained in:
jeffvli 2023-08-04 19:32:41 -07:00
parent 72b4a60c7b
commit fca135ce2b
7 changed files with 230 additions and 64 deletions

View file

@ -0,0 +1,26 @@
.lyric-line {
color: var(--main-fg);
font-weight: 400;
font-size: 2.5vmax;
transform: scale(0.95);
opacity: 0.5;
.active {
font-weight: 800 !important;
transform: scale(1) !important;
opacity: 1;
}
.active.unsynchronized {
opacity: 0.8;
}
transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
}
.lyric-line.active {
font-weight: 800;
transform: scale(1);
opacity: 1;
}

View file

@ -1,31 +1,41 @@
import { ComponentPropsWithoutRef } from 'react';
import { TextTitle } from '/@/renderer/components/text-title';
import { TitleProps } from '@mantine/core';
import styled from 'styled-components';
interface LyricLineProps extends ComponentPropsWithoutRef<'div'> {
alignment: 'left' | 'center' | 'right';
fontSize: number;
text: string;
}
const StyledText = styled(TextTitle)`
const StyledText = styled(TextTitle)<TitleProps & { $alignment: string; $fontSize: number }>`
color: var(--main-fg);
font-weight: 400;
font-size: 2.5vmax;
transform: scale(0.95);
text-align: ${(props) => props.$alignment};
font-size: ${(props) => props.$fontSize}px;
opacity: 0.5;
&.active {
font-weight: 800;
transform: scale(1);
opacity: 1;
}
&.active.unsynchronized {
opacity: 0.8;
&.unsynchronized {
opacity: 1;
}
transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
`;
export const LyricLine = ({ text, ...props }: LyricLineProps) => {
return <StyledText {...props}>{text}</StyledText>;
export const LyricLine = ({ text, alignment, fontSize, ...props }: LyricLineProps) => {
return (
<StyledText
$alignment={alignment}
$fontSize={fontSize}
{...props}
>
{text}
</StyledText>
);
};

View file

@ -15,10 +15,10 @@ import styled from 'styled-components';
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
const SynchronizedLyricsContainer = styled.div`
const SynchronizedLyricsContainer = styled.div<{ $gap: number }>`
display: flex;
flex-direction: column;
gap: 2rem;
gap: ${(props) => props.$gap || 5}px;
width: 100%;
height: 100%;
padding: 10vh 0 6vh;
@ -146,7 +146,8 @@ export const SynchronizedLyrics = ({
'sychronized-lyrics-scroll-container',
) as HTMLElement;
const currentLyric = document.querySelector(`#lyric-${index}`) as HTMLElement;
const offsetTop = currentLyric.offsetTop - doc.clientHeight / 2 ?? 0;
// eslint-disable-next-line no-unsafe-optional-chaining
const offsetTop = currentLyric?.offsetTop - doc?.clientHeight / 2 ?? 0;
if (currentLyric === null) {
lyricRef.current = undefined;
@ -295,27 +296,34 @@ export const SynchronizedLyrics = ({
return (
<SynchronizedLyricsContainer
$gap={settings.gap}
className="synchronized-lyrics overlay-scrollbar"
id="sychronized-lyrics-scroll-container"
onMouseEnter={showScrollbar}
onMouseLeave={hideScrollbar}
>
{source && (
{settings.showProvider && source && (
<LyricLine
alignment={settings.alignment}
className="lyric-credit"
fontSize={settings.fontSize}
text={`Provided by ${source}`}
/>
)}
{remote && (
{settings.showMatch && remote && (
<LyricLine
alignment={settings.alignment}
className="lyric-credit"
fontSize={settings.fontSize}
text={`"${name} by ${artist}"`}
/>
)}
{lyrics.map(([, text], idx) => (
<LyricLine
key={idx}
alignment={settings.alignment}
className="lyric-line synchronized"
fontSize={settings.fontSize}
id={`lyric-${idx}`}
text={text}
/>

View file

@ -2,15 +2,16 @@ import { useMemo } from 'react';
import styled from 'styled-components';
import { LyricLine } from '/@/renderer/features/lyrics/lyric-line';
import { FullLyricsMetadata } from '/@/renderer/api/types';
import { useLyricsSettings } from '/@/renderer/store';
interface UnsynchronizedLyricsProps extends Omit<FullLyricsMetadata, 'lyrics'> {
lyrics: string;
}
const UnsynchronizedLyricsContainer = styled.div`
const UnsynchronizedLyricsContainer = styled.div<{ $gap: number }>`
display: flex;
flex-direction: column;
gap: 2rem;
gap: ${(props) => props.$gap || 5}px;
width: 100%;
height: 100%;
padding: 10vh 0 6vh;
@ -37,28 +38,38 @@ export const UnsynchronizedLyrics = ({
remote,
source,
}: UnsynchronizedLyricsProps) => {
const settings = useLyricsSettings();
const lines = useMemo(() => {
return lyrics.split('\n');
}, [lyrics]);
return (
<UnsynchronizedLyricsContainer className="unsynchronized-lyrics">
<UnsynchronizedLyricsContainer
$gap={settings.gapUnsync}
className="unsynchronized-lyrics"
>
{source && (
<LyricLine
alignment={settings.alignment}
className="lyric-credit"
fontSize={settings.fontSizeUnsync}
text={`Provided by ${source}`}
/>
)}
{remote && (
<LyricLine
alignment={settings.alignment}
className="lyric-credit"
fontSize={settings.fontSizeUnsync}
text={`"${name} by ${artist}"`}
/>
)}
{lines.map((text, idx) => (
<LyricLine
key={idx}
className="lyric-line"
alignment={settings.alignment}
className="lyric-line unsynchronized"
fontSize={settings.fontSizeUnsync}
id={`lyric-${idx}`}
text={text}
/>