mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-27 22:37:39 +02:00
Compare commits
2 Commits
b6519e9839
...
0fab3ba318
| Author | SHA1 | Date | |
|---|---|---|---|
| 0fab3ba318 | |||
| 5ddbfcbfee |
@@ -973,7 +973,43 @@
|
|||||||
"autoDJ_albumStrategy": "Mode de selecció d'àlbum",
|
"autoDJ_albumStrategy": "Mode de selecció d'àlbum",
|
||||||
"autoDJ_songStrategy": "Mode de selecció de cançó",
|
"autoDJ_songStrategy": "Mode de selecció de cançó",
|
||||||
"autoDJ_strategy_option_library_random": "A l'atzar",
|
"autoDJ_strategy_option_library_random": "A l'atzar",
|
||||||
"autoDJ_strategy_option_similar": "Similar"
|
"autoDJ_strategy_option_similar": "Similar",
|
||||||
|
"enableFurigana_description": "Mostra guies de pronunciació (furigana) per les lletres en japonès.",
|
||||||
|
"enableFurigana": "Activa la generació de furigana",
|
||||||
|
"equalizer_descriptionMpv": "Equalitzador paramètric amb FFmpeg lavfi (MPV)",
|
||||||
|
"equalizer_descriptionWebAudio": "Equalitzador paramètric amb l'API de Web Audio",
|
||||||
|
"equalizer": "Equalitzador",
|
||||||
|
"equalizerBands_description": "Guany per banda. Arrossegueu-lo amunt o avall, o introduïu-hi un valor. Rang: -12 a +12 dB.",
|
||||||
|
"equalizerBands": "Bandes",
|
||||||
|
"equalizerPreamp_description": "Guany d'entrada previ a les bandes de l'equalitzador. Poseu-lo en negatiu quan realceu les bandes per evitar el clipping (MPV).",
|
||||||
|
"equalizerPreamp": "Preamplificador",
|
||||||
|
"equalizerPreset_description": "Aplica una corba d'equalitzador personalitzada integrada o desada",
|
||||||
|
"equalizerPreset": "Preajustament",
|
||||||
|
"equalizerPresetDeletePlaceholder": "Elimina la personalització...",
|
||||||
|
"equalizerPresetGroupBuiltIn": "Integrat",
|
||||||
|
"equalizerPresetGroupCustom": "Personalitzat",
|
||||||
|
"equalizerPresetNamePlaceholder": "Nom de l'ajust predefinit...",
|
||||||
|
"equalizerPresetSelectPlaceholder": "Seleccioneu un ajust predefinit",
|
||||||
|
"equalizerSavePreset_description": "Desa la configuració actual de l'equalitzador com a ajust predefinit amb nom",
|
||||||
|
"equalizerSavePreset": "Desa l'ajust",
|
||||||
|
"compressor_descriptionMpv": "Compressor de rang dinàmic amb el compressor de FFmpeg (MPV)",
|
||||||
|
"compressor_descriptionWebAudio": "Compressor de rang dinàmic amb l'API de Web Audio",
|
||||||
|
"compressor": "Compressor",
|
||||||
|
"compressorAttack_description": "La rapidesa amb què el compressor s'activa quan el senyal excedeix el llindar.",
|
||||||
|
"compressorAttack": "Atac",
|
||||||
|
"compressorKnee_description": "Amplada de la zona de resposta suau. Com més alt sigui, més gradual serà la transició cap a la compressió.",
|
||||||
|
"compressorKnee": "Zona de resposta",
|
||||||
|
"compressorMakeupGain_description": "Guany de sortida aplicat després de la compressió per recuperar volum.",
|
||||||
|
"compressorMakeupGain": "Guany de compensació",
|
||||||
|
"compressorPreset_description": "Aplica una configuració personalitzada del compressor integrada o desada",
|
||||||
|
"compressorRatio_description": "Ràtio de compressio, p. ex. 4 = 4:1.",
|
||||||
|
"compressorRatio": "Ràtio",
|
||||||
|
"compressorRelease_description": "Com de ràpid el compressor es desactiva un cop el senyal sigui inferior al llindar.",
|
||||||
|
"compressorRelease": "Desactivació",
|
||||||
|
"compressorReset_description": "Restaura tots els paràmetres del compressor als seus valors per defecte",
|
||||||
|
"compressorSavePreset_description": "Desa la configuració actual del compressor com un ajust predefinit amb nom",
|
||||||
|
"compressorThreshold_description": "Nivell de senyal a partir del qual comença la compressió.",
|
||||||
|
"compressorThreshold": "Llindar"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"column": {
|
"column": {
|
||||||
@@ -1266,7 +1302,9 @@
|
|||||||
"notContains": "No conté",
|
"notContains": "No conté",
|
||||||
"notInPlaylist": "No és a",
|
"notInPlaylist": "No és a",
|
||||||
"notInTheLast": "No és a l'últim",
|
"notInTheLast": "No és a l'últim",
|
||||||
"startsWith": "Comença amb"
|
"startsWith": "Comença amb",
|
||||||
|
"isMissing": "Falta",
|
||||||
|
"isPresent": "Està present"
|
||||||
},
|
},
|
||||||
"queryBuilder": {
|
"queryBuilder": {
|
||||||
"standardTags": "Etiquetes estàndard",
|
"standardTags": "Etiquetes estàndard",
|
||||||
|
|||||||
@@ -1135,7 +1135,43 @@
|
|||||||
"queryBuilderCustomFields_inputLabel": "Nimetus",
|
"queryBuilderCustomFields_inputLabel": "Nimetus",
|
||||||
"queryBuilderCustomFields_inputTag": "Silt",
|
"queryBuilderCustomFields_inputTag": "Silt",
|
||||||
"queryBuilderCustomFields": "Kohandatud väljad",
|
"queryBuilderCustomFields": "Kohandatud väljad",
|
||||||
"queryBuilderCustomFields_description": "Lisa kohandatud välju, mida päringukoosturis kasutada"
|
"queryBuilderCustomFields_description": "Lisa kohandatud välju, mida päringukoosturis kasutada",
|
||||||
|
"equalizer_descriptionMpv": "Parametriline ekvalaiser FFmpeg lavfi (MPV) kaudu",
|
||||||
|
"equalizer_descriptionWebAudio": "Parametriline ekvalaiser Web Audio API kaudu",
|
||||||
|
"equalizer": "Ekvalaiser",
|
||||||
|
"equalizerBands_description": "Riba põhivõimendus. Lohista üles/alla või sisesta väärtus. Vahemik: -12 kuni +12 dB.",
|
||||||
|
"equalizerBands": "Ribad",
|
||||||
|
"equalizerPreamp_description": "Sisendvõimendus enne ekvalaiseri ribasid. Moonutuste vältimiseks määra ribade võimendamisel negatiivne väärtus (MPV).",
|
||||||
|
"equalizerPreamp": "Eelvõimendus",
|
||||||
|
"equalizerPreset_description": "Rakenda sisseehitatud või salvestatud kohandatud EQ-häälestus",
|
||||||
|
"equalizerPreset": "Eelseadistus",
|
||||||
|
"equalizerPresetDeletePlaceholder": "Kustuta kohandatud...",
|
||||||
|
"equalizerPresetGroupBuiltIn": "Sisseehitatud",
|
||||||
|
"equalizerPresetGroupCustom": "Kohandatud",
|
||||||
|
"equalizerPresetNamePlaceholder": "Eelseadistuse nimi...",
|
||||||
|
"equalizerPresetSelectPlaceholder": "Vali eelseadistus",
|
||||||
|
"equalizerSavePreset_description": "Salvesta praegused EQ-seaded nimetatud eelseadistusena",
|
||||||
|
"equalizerSavePreset": "Salvesta eelseadistus",
|
||||||
|
"compressor_descriptionMpv": "Dünaamilise vahemiku kompressor FFmpeg acompressori kaudu (MPV)",
|
||||||
|
"compressor_descriptionWebAudio": "Dünaamilise vahemiku kompressor Web Audio API kaudu",
|
||||||
|
"enableFurigana_description": "Kuva jaapani kanji-märkide kohal hääldusjuhiseid (furigana).",
|
||||||
|
"enableFurigana": "Luba furigana kuvamine",
|
||||||
|
"compressor": "Kompressor",
|
||||||
|
"compressorAttack_description": "Kui kiiresti kompressor pärast läve ületamist rakendub.",
|
||||||
|
"compressorAttack": "Rakendumisaeg",
|
||||||
|
"compressorKnee_description": "Sujuva ülemineku (soft-knee) ulatus. Suuremad väärtused muudavad kompressiooni rakendumise astmelisemaks.",
|
||||||
|
"compressorKnee": "Üleminek",
|
||||||
|
"compressorMakeupGain_description": "Väljundvõimendus helitugevuse taastamiseks pärast kompressiooni.",
|
||||||
|
"compressorMakeupGain": "Väljundvõimendus",
|
||||||
|
"compressorPreset_description": "Rakenda sisseehitatud või salvestatud kohandatud kompressoriseadistus",
|
||||||
|
"compressorRatio_description": "Kompressiooniaste, nt 4 = 4:1.",
|
||||||
|
"compressorRatio": "Kompressiooniaste",
|
||||||
|
"compressorRelease_description": "Kui kiiresti kompressiooni mõju pärast lävest allapoole langemist lakkab.",
|
||||||
|
"compressorRelease": "Vabastusaeg",
|
||||||
|
"compressorReset_description": "Taasta kõigi kompressori parameetrite vaikeväärtused",
|
||||||
|
"compressorSavePreset_description": "Salvesta praegused kompressori seaded nimetatud eelseadistusena",
|
||||||
|
"compressorThreshold_description": "Signaali tase, mida ületades kompressioon algab.",
|
||||||
|
"compressorThreshold": "Lävi"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"minuteShort": "m",
|
"minuteShort": "m",
|
||||||
|
|||||||
@@ -1108,7 +1108,43 @@
|
|||||||
"autoDJ_albumStrategy": "Tryb wyboru albumów",
|
"autoDJ_albumStrategy": "Tryb wyboru albumów",
|
||||||
"autoDJ_songStrategy": "Tryb wyboru piosenek",
|
"autoDJ_songStrategy": "Tryb wyboru piosenek",
|
||||||
"autoDJ_strategy_option_library_random": "Losowo",
|
"autoDJ_strategy_option_library_random": "Losowo",
|
||||||
"autoDJ_strategy_option_similar": "Podobne"
|
"autoDJ_strategy_option_similar": "Podobne",
|
||||||
|
"enableFurigana_description": "Wyświetlaj pomoce wymowy (furigana) nad tekstami Japońskimi kanji.",
|
||||||
|
"enableFurigana": "Włącz generowanie furigana",
|
||||||
|
"equalizer_descriptionMpv": "Equalizer parametryczny przez FFmpeg lavfi (MPV)",
|
||||||
|
"equalizer_descriptionWebAudio": "Parametryczny equalizer przez API Web Audio",
|
||||||
|
"equalizer": "Equalizer",
|
||||||
|
"equalizerBands_description": "Wzmocnienie dla poszczególnych pasm. Przesuń w górę/dół lub wpisz wartość. Zakres: -12 do +12 dB.",
|
||||||
|
"equalizerBands": "Pasma",
|
||||||
|
"equalizerPreamp_description": "Wzmocnienie sygnału przed pasmami EQ. Ustaw na wartość ujemną podczas wzmacniania pasm, aby zapobiec przesterowaniu (MPV).",
|
||||||
|
"equalizerPreamp": "Przedwzmacnianie",
|
||||||
|
"equalizerPreset_description": "Zastosuj wbudowaną lub niestandardową zapisaną krzywą EQ",
|
||||||
|
"equalizerPreset": "Ustawienia wstępne",
|
||||||
|
"equalizerPresetDeletePlaceholder": "Usuń niestandardowe...",
|
||||||
|
"equalizerPresetGroupBuiltIn": "Wbudowane",
|
||||||
|
"equalizerPresetGroupCustom": "Niestandardowe",
|
||||||
|
"equalizerPresetNamePlaceholder": "Nazwa ustawień wstępnych...",
|
||||||
|
"equalizerPresetSelectPlaceholder": "Wybierz ustawienia wstępne",
|
||||||
|
"equalizerSavePreset_description": "Zapisz aktualne ustawienia EQ jako nazwany zestaw ustawień wstępnych",
|
||||||
|
"equalizerSavePreset": "Zapisz ustawienia wstępne",
|
||||||
|
"compressor_descriptionMpv": "Kompresor zakresu dynamicznego przez FFmpeg acompressor (MPV)",
|
||||||
|
"compressor_descriptionWebAudio": "Kompresor zakresu dynamicznego poprzez API Web Audio",
|
||||||
|
"compressor": "Kompresor",
|
||||||
|
"compressorAttack_description": "Jak szybko załączany jest kompresor po przekroczeniu progu przez sygnał.",
|
||||||
|
"compressorAttack": "Attack",
|
||||||
|
"compressorKnee_description": "Szerokośc soft-knee. Większe wartości powodują przejście do kompresji bardziej stopniowym.",
|
||||||
|
"compressorKnee": "Knee",
|
||||||
|
"compressorMakeupGain_description": "Zwiększenie wyjściowe dodawane po kompresji aby, przywrócić głośność.",
|
||||||
|
"compressorMakeupGain": "Makeup Gain",
|
||||||
|
"compressorPreset_description": "Zastosuj wbudowane lub niestandardowe zapisane ustawienie kompresora",
|
||||||
|
"compressorRatio_description": "Proporcje kompresji, np. 4 = 4:1.",
|
||||||
|
"compressorRatio": "Proporcje",
|
||||||
|
"compressorRelease_description": "Jak szybko kompresor odpuszcza po spadnięciu sygnału poniżej progu.",
|
||||||
|
"compressorRelease": "Odpuszczenie",
|
||||||
|
"compressorReset_description": "Przywróć wszystkie parametry kompresora do wartości domyślnych",
|
||||||
|
"compressorSavePreset_description": "Zapisz aktualne ustawienia kompresora jako nazwany zestaw ustawień wstępnych",
|
||||||
|
"compressorThreshold_description": "Poziom sygnału nad którym rozpoczyna się kompresja.",
|
||||||
|
"compressorThreshold": "Próg"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"config": {
|
"config": {
|
||||||
|
|||||||
+10
-4
@@ -64,6 +64,7 @@ export const useItemDragDropState = <TElement extends HTMLElement = HTMLDivEleme
|
|||||||
return draggedItems;
|
return draggedItems;
|
||||||
},
|
},
|
||||||
itemType,
|
itemType,
|
||||||
|
metadata: { playlistId },
|
||||||
onDragStart: () => {
|
onDragStart: () => {
|
||||||
if (!item || !isDataRow) {
|
if (!item || !isDataRow) {
|
||||||
return;
|
return;
|
||||||
@@ -248,10 +249,15 @@ export const useItemDragDropState = <TElement extends HTMLElement = HTMLDivEleme
|
|||||||
case DragTarget.SONG: {
|
case DragTarget.SONG: {
|
||||||
const sourceItems = (args.source.item || []) as Song[];
|
const sourceItems = (args.source.item || []) as Song[];
|
||||||
if (sourceItems.length > 0) {
|
if (sourceItems.length > 0) {
|
||||||
playerContext.addToQueueByData(sourceItems, {
|
const sourcePlaylistId = args.source.metadata?.playlistId as
|
||||||
edge: args.edge,
|
| string
|
||||||
uniqueId: droppedOnUniqueId,
|
| undefined;
|
||||||
});
|
playerContext.addToQueueByData(
|
||||||
|
sourceItems,
|
||||||
|
{ edge: args.edge, uniqueId: droppedOnUniqueId },
|
||||||
|
undefined,
|
||||||
|
sourcePlaylistId ?? null,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,12 @@ import {
|
|||||||
import { Play, PlayerRepeat, PlayerShuffle } from '/@/shared/types/types';
|
import { Play, PlayerRepeat, PlayerShuffle } from '/@/shared/types/types';
|
||||||
|
|
||||||
export interface PlayerContext {
|
export interface PlayerContext {
|
||||||
addToQueueByData: (data: Song[], type: AddToQueueType, playSongId?: string) => void;
|
addToQueueByData: (
|
||||||
|
data: Song[],
|
||||||
|
type: AddToQueueType,
|
||||||
|
playSongId?: string,
|
||||||
|
contextPlaylistId?: null | string,
|
||||||
|
) => void;
|
||||||
addToQueueByFetch: (
|
addToQueueByFetch: (
|
||||||
serverId: string,
|
serverId: string,
|
||||||
id: string[],
|
id: string[],
|
||||||
@@ -137,6 +142,23 @@ const getRootQueryKey = (itemType: LibraryItem, serverId: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isReplaceQueueType = (type: AddToQueueType): boolean => {
|
||||||
|
if (typeof type === 'object') return false;
|
||||||
|
return type === Play.NOW || type === Play.SHUFFLE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// HashRouter puts the route in location.hash, not pathname.
|
||||||
|
const inferPlaylistContextFromUrl = (): null | string => {
|
||||||
|
const route = window.location.hash.replace(/^#/, '');
|
||||||
|
const match = route.match(/^\/playlists\/([^/]+)/);
|
||||||
|
return match ? match[1] : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Stamps each song with the playlist it was queued from, so the sidebar highlight
|
||||||
|
// can be derived from whichever song is currently playing (see useCurrentPlaylistContextId).
|
||||||
|
const tagPlaylistContext = (songs: Song[], contextPlaylistId: string): Song[] =>
|
||||||
|
songs.map((song) => ({ ...song, _contextPlaylistId: contextPlaylistId }));
|
||||||
|
|
||||||
export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
@@ -187,9 +209,20 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
}, [doNotShowAgain, setDoNotShowAgain, t]);
|
}, [doNotShowAgain, setDoNotShowAgain, t]);
|
||||||
|
|
||||||
const addToQueueByData = useCallback(
|
const addToQueueByData = useCallback(
|
||||||
(data: Song[], type: AddToQueueType, playSongId?: string) => {
|
(
|
||||||
|
data: Song[],
|
||||||
|
type: AddToQueueType,
|
||||||
|
playSongId?: string,
|
||||||
|
contextPlaylistId?: null | string,
|
||||||
|
) => {
|
||||||
const filters = useSettingsStore.getState().playback.filters;
|
const filters = useSettingsStore.getState().playback.filters;
|
||||||
const filteredData = filterSongsByPlayerFilters(data, filters);
|
let filteredData = filterSongsByPlayerFilters(data, filters);
|
||||||
|
const resolvedContextId =
|
||||||
|
contextPlaylistId ??
|
||||||
|
(isReplaceQueueType(type) ? inferPlaylistContextFromUrl() : null);
|
||||||
|
if (resolvedContextId) {
|
||||||
|
filteredData = tagPlaylistContext(filteredData, resolvedContextId);
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof type === 'object' && 'edge' in type && type.edge !== null) {
|
if (typeof type === 'object' && 'edge' in type && type.edge !== null) {
|
||||||
const edge = type.edge === 'top' ? 'top' : 'bottom';
|
const edge = type.edge === 'top' ? 'top' : 'bottom';
|
||||||
@@ -279,7 +312,21 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const filters = useSettingsStore.getState().playback.filters;
|
const filters = useSettingsStore.getState().playback.filters;
|
||||||
const filteredSongs = filterSongsByPlayerFilters(sortedSongs, filters);
|
let filteredSongs = filterSongsByPlayerFilters(sortedSongs, filters);
|
||||||
|
|
||||||
|
// Songs from multiple playlists are merged together, so there is no single
|
||||||
|
// playlist to attribute them to: skip tagging (and URL inference) entirely.
|
||||||
|
const isMultiPlaylist = itemType === LibraryItem.PLAYLIST && id.length > 1;
|
||||||
|
const explicitId =
|
||||||
|
itemType === LibraryItem.PLAYLIST && id.length === 1 ? id[0] : null;
|
||||||
|
const resolvedContextId =
|
||||||
|
explicitId ??
|
||||||
|
(!isMultiPlaylist && isReplaceQueueType(type)
|
||||||
|
? inferPlaylistContextFromUrl()
|
||||||
|
: null);
|
||||||
|
if (resolvedContextId) {
|
||||||
|
filteredSongs = tagPlaylistContext(filteredSongs, resolvedContextId);
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof type === 'object' && 'edge' in type && type.edge !== null) {
|
if (typeof type === 'object' && 'edge' in type && type.edge !== null) {
|
||||||
const edge = type.edge === 'top' ? 'top' : 'bottom';
|
const edge = type.edge === 'top' ? 'top' : 'bottom';
|
||||||
|
|||||||
@@ -136,6 +136,10 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.name-active {
|
||||||
|
color: var(--theme-colors-primary);
|
||||||
|
}
|
||||||
|
|
||||||
.image-container {
|
.image-container {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import { useDragDrop } from '/@/renderer/hooks/use-drag-drop';
|
|||||||
import { useDragMonitor } from '/@/renderer/hooks/use-drag-monitor';
|
import { useDragMonitor } from '/@/renderer/hooks/use-drag-monitor';
|
||||||
import { AppRoute } from '/@/renderer/router/routes';
|
import { AppRoute } from '/@/renderer/router/routes';
|
||||||
import {
|
import {
|
||||||
|
useCurrentPlaylistContextId,
|
||||||
useCurrentServer,
|
useCurrentServer,
|
||||||
useCurrentServerId,
|
useCurrentServerId,
|
||||||
usePermissions,
|
usePermissions,
|
||||||
@@ -116,6 +117,8 @@ export const PlaylistRowButton = memo(
|
|||||||
const sidebarPlaylistSorting = useSidebarPlaylistSorting();
|
const sidebarPlaylistSorting = useSidebarPlaylistSorting();
|
||||||
const sidebarPlaylistMode = useSidebarPlaylistMode();
|
const sidebarPlaylistMode = useSidebarPlaylistMode();
|
||||||
const isCompact = sidebarPlaylistMode === 'compact';
|
const isCompact = sidebarPlaylistMode === 'compact';
|
||||||
|
const activePlaylistId = useCurrentPlaylistContextId();
|
||||||
|
const isActive = activePlaylistId === item.id;
|
||||||
|
|
||||||
const [isHovered, setIsHovered] = useState(false);
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
const isSmartPlaylist = Boolean(item.rules);
|
const isSmartPlaylist = Boolean(item.rules);
|
||||||
@@ -292,7 +295,13 @@ export const PlaylistRowButton = memo(
|
|||||||
>
|
>
|
||||||
{isCompact ? (
|
{isCompact ? (
|
||||||
<>
|
<>
|
||||||
<Text className={styles.compactName} fw={500} size="md">
|
<Text
|
||||||
|
className={clsx(styles.compactName, {
|
||||||
|
[styles.nameActive]: isActive,
|
||||||
|
})}
|
||||||
|
fw={500}
|
||||||
|
size="md"
|
||||||
|
>
|
||||||
{name}
|
{name}
|
||||||
</Text>
|
</Text>
|
||||||
{isHovered && (
|
{isHovered && (
|
||||||
@@ -307,7 +316,13 @@ export const PlaylistRowButton = memo(
|
|||||||
<div className={styles.rowGroup}>
|
<div className={styles.rowGroup}>
|
||||||
<Image containerClassName={styles.imageContainer} src={imageUrl} />
|
<Image containerClassName={styles.imageContainer} src={imageUrl} />
|
||||||
<div className={styles.metadata}>
|
<div className={styles.metadata}>
|
||||||
<Text className={styles.name} fw={500} size="md">
|
<Text
|
||||||
|
className={clsx(styles.name, {
|
||||||
|
[styles.nameActive]: isActive,
|
||||||
|
})}
|
||||||
|
fw={500}
|
||||||
|
size="md"
|
||||||
|
>
|
||||||
{name}
|
{name}
|
||||||
</Text>
|
</Text>
|
||||||
<div className={styles.metadataGroup}>
|
<div className={styles.metadataGroup}>
|
||||||
|
|||||||
@@ -1640,6 +1640,7 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
|
|||||||
const excludedPlayerKeys = ['playerNum', 'seekToTimestamp', 'status'];
|
const excludedPlayerKeys = ['playerNum', 'seekToTimestamp', 'status'];
|
||||||
|
|
||||||
// If we're not restoring the play queue, we don't need the index property
|
// If we're not restoring the play queue, we don't need the index property
|
||||||
|
// (it is meaningless without the queue)
|
||||||
if (!shouldRestorePlayQueue) {
|
if (!shouldRestorePlayQueue) {
|
||||||
excludedPlayerKeys.push('index');
|
excludedPlayerKeys.push('index');
|
||||||
}
|
}
|
||||||
@@ -2076,6 +2077,7 @@ export const updateQueueSong = (songId: string, updatedSong: Song) => {
|
|||||||
const uniqueId = song._uniqueId;
|
const uniqueId = song._uniqueId;
|
||||||
state.queue.songs[song._uniqueId] = {
|
state.queue.songs[song._uniqueId] = {
|
||||||
...updatedSong,
|
...updatedSong,
|
||||||
|
_contextPlaylistId: song._contextPlaylistId,
|
||||||
_uniqueId: uniqueId,
|
_uniqueId: uniqueId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -2083,6 +2085,10 @@ export const updateQueueSong = (songId: string, updatedSong: Song) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useCurrentPlaylistContextId = () => {
|
||||||
|
return usePlayerStoreBase((state) => state.getCurrentSong()?._contextPlaylistId ?? null);
|
||||||
|
};
|
||||||
|
|
||||||
export const usePlayerMuted = () => {
|
export const usePlayerMuted = () => {
|
||||||
return usePlayerStoreBase((state) => state.player.muted);
|
return usePlayerStoreBase((state) => state.player.muted);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ export interface QueueData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type QueueSong = Song & {
|
export type QueueSong = Song & {
|
||||||
|
_contextPlaylistId?: null | string;
|
||||||
_uniqueId: string;
|
_uniqueId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user