mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-08 13:00:13 +02:00
add sidebar panel lyrics
This commit is contained in:
@@ -1,12 +1,17 @@
|
||||
import clsx from 'clsx';
|
||||
import isElectron from 'is-electron';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
|
||||
import styles from './synchronized-lyrics.module.css';
|
||||
|
||||
import { LyricLine } from '/@/renderer/features/lyrics/lyric-line';
|
||||
import { usePlayerEvents } from '/@/renderer/features/player/audio-player/hooks/use-player-events';
|
||||
import { useLyricsSettings, usePlaybackType, usePlayerActions } from '/@/renderer/store';
|
||||
import {
|
||||
useLyricsSettings,
|
||||
usePlaybackType,
|
||||
usePlayerActions,
|
||||
usePlayerStatus,
|
||||
} from '/@/renderer/store';
|
||||
import { usePlayerTimestamp } from '/@/renderer/store/timestamp.store';
|
||||
import { FullLyricsMetadata, SynchronizedLyricsArray } from '/@/shared/types/domain-types';
|
||||
import { PlayerStatus, PlayerType } from '/@/shared/types/types';
|
||||
|
||||
@@ -30,10 +35,8 @@ export const SynchronizedLyrics = ({
|
||||
const playbackType = usePlaybackType();
|
||||
const settings = useLyricsSettings();
|
||||
const { mediaSeekToTimestamp } = usePlayerActions();
|
||||
|
||||
// State for player status and timestamp from events
|
||||
const [status, setStatus] = useState<PlayerStatus>(PlayerStatus.PAUSED);
|
||||
const [timestamp, setTimestamp] = useState<number>(0);
|
||||
const status = usePlayerStatus();
|
||||
const timestamp = usePlayerTimestamp();
|
||||
|
||||
const handleSeek = useCallback(
|
||||
(time: number) => {
|
||||
@@ -154,23 +157,6 @@ export const SynchronizedLyrics = ({
|
||||
setCurrentLyricRef.current = setCurrentLyric;
|
||||
}, [setCurrentLyric]);
|
||||
|
||||
// Subscribe to player events
|
||||
usePlayerEvents(
|
||||
{
|
||||
onPlayerProgress: (properties) => {
|
||||
setTimestamp(properties.timestamp);
|
||||
},
|
||||
onPlayerSeekToTimestamp: (properties) => {
|
||||
// When seeking, update timestamp immediately
|
||||
setTimestamp(properties.timestamp);
|
||||
},
|
||||
onPlayerStatus: (properties) => {
|
||||
setStatus(properties.status);
|
||||
},
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// Copy the follow settings into a ref that can be accessed in the timeout
|
||||
followRef.current = settings.follow;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
.play-queue-section {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.lyrics-section {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: 0 0 300px;
|
||||
flex-direction: column;
|
||||
min-height: 200px;
|
||||
max-height: 400px;
|
||||
overflow: hidden;
|
||||
background: var(--theme-colors-background);
|
||||
}
|
||||
|
||||
.lyrics-section :global(.synchronized-lyrics) {
|
||||
padding: 2rem 0 4rem !important;
|
||||
transform: translateY(0) !important;
|
||||
}
|
||||
|
||||
.lyrics-section :global(.synchronized-lyrics .lyric-line) {
|
||||
padding: 0.25rem 0;
|
||||
}
|
||||
@@ -1,14 +1,21 @@
|
||||
import { useRef, useState } from 'react';
|
||||
|
||||
import styles from './sidebar-play-queue.module.css';
|
||||
|
||||
import { ItemListHandle } from '/@/renderer/components/item-list/types';
|
||||
import { Lyrics } from '/@/renderer/features/lyrics/lyrics';
|
||||
import { PlayQueue } from '/@/renderer/features/now-playing/components/play-queue';
|
||||
import { PlayQueueListControls } from '/@/renderer/features/now-playing/components/play-queue-list-controls';
|
||||
import { useLyricsSettings } from '/@/renderer/store';
|
||||
import { Divider } from '/@/shared/components/divider/divider';
|
||||
import { Flex } from '/@/shared/components/flex/flex';
|
||||
import { Stack } from '/@/shared/components/stack/stack';
|
||||
import { ItemListKey } from '/@/shared/types/types';
|
||||
|
||||
export const SidebarPlayQueue = () => {
|
||||
const tableRef = useRef<ItemListHandle | null>(null);
|
||||
const [search, setSearch] = useState<string | undefined>(undefined);
|
||||
const { showLyricsInSidebar } = useLyricsSettings();
|
||||
|
||||
return (
|
||||
<Stack gap={0} h="100%" id="sidebar-play-queue-container" pos="relative" w="100%">
|
||||
@@ -18,7 +25,23 @@ export const SidebarPlayQueue = () => {
|
||||
tableRef={tableRef}
|
||||
type={ItemListKey.SIDE_QUEUE}
|
||||
/>
|
||||
<PlayQueue listKey={ItemListKey.SIDE_QUEUE} ref={tableRef} searchTerm={search} />
|
||||
<Flex direction="column" style={{ flex: 1, minHeight: 0 }}>
|
||||
<div className={styles.playQueueSection}>
|
||||
<PlayQueue
|
||||
listKey={ItemListKey.SIDE_QUEUE}
|
||||
ref={tableRef}
|
||||
searchTerm={search}
|
||||
/>
|
||||
</div>
|
||||
{showLyricsInSidebar && (
|
||||
<>
|
||||
<Divider />
|
||||
<div className={styles.lyricsSection}>
|
||||
<Lyrics />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -43,6 +43,27 @@ export const LyricSettings = () => {
|
||||
}),
|
||||
title: t('setting.followLyric', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
aria-label="Show lyrics in attached play queue"
|
||||
defaultChecked={settings.showLyricsInSidebar}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
lyrics: {
|
||||
...settings,
|
||||
showLyricsInSidebar: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
),
|
||||
description: t('setting.showLyricsInSidebar', {
|
||||
context: 'description',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
title: t('setting.showLyricsInSidebar', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Switch
|
||||
|
||||
Reference in New Issue
Block a user