) {
return (
);
}
function Controls() {
const [isPlaying, shuffle, repeat] = useStateFromStores(
[SpotifyStore],
() => [SpotifyStore.isPlaying, SpotifyStore.shuffle, SpotifyStore.repeat]
);
const [nextRepeat, repeatClassName] = (() => {
switch (repeat) {
case "off": return ["context", "repeat-off"] as const;
case "context": return ["track", "repeat-context"] as const;
case "track": return ["off", "repeat-track"] as const;
default: throw new Error(`Invalid repeat state ${repeat}`);
}
})();
// the 1 is using position absolute so it does not make the button jump around
return (
);
}
const seek = debounce((v: number) => {
SpotifyStore.seek(v);
});
const Slider = LazyComponent(() => {
const filter = filters.byCode("sliderContainer");
return find(m => m.render && filter(m.render));
});
function SeekBar() {
const { duration } = SpotifyStore.track!;
const [storePosition, isSettingPosition, isPlaying] = useStateFromStores(
[SpotifyStore],
() => [SpotifyStore.mPosition, SpotifyStore.isSettingPosition, SpotifyStore.isPlaying]
);
const [position, setPosition] = React.useState(storePosition);
// eslint-disable-next-line consistent-return
React.useEffect(() => {
if (isPlaying && !isSettingPosition) {
setPosition(SpotifyStore.position);
const interval = setInterval(() => {
setPosition(p => p + 1000);
}, 1000);
return () => clearInterval(interval);
}
}, [storePosition, isSettingPosition, isPlaying]);
return (
{msToHuman(position)}
{
if (isSettingPosition) return;
setPosition(v);
seek(v);
}}
renderValue={msToHuman}
/>
{msToHuman(duration)}
);
}
function AlbumContextMenu({ track }: { track: Track; }) {
const volume = useStateFromStores([SpotifyStore], () => SpotifyStore.volume);
return (
FluxDispatcher.dispatch({ type: "CONTEXT_MENU_CLOSE" })}
aria-label="Spotify Album Menu"
>
SpotifyStore.openExternal(`/album/${track.album.id}`)}
/>
(Vencord.Plugins.plugins.ViewIcons as any).openImage(track.album.image.url)}
/>
(
SpotifyStore.setVolume(v))}
/>
)}
/>
);
}
function Info({ track }: { track: Track; }) {
const img = track?.album?.image;
const [coverExpanded, setCoverExpanded] = React.useState(false);
const i = (
<>
{img && (
setCoverExpanded(!coverExpanded)}
onContextMenu={e => {
ContextMenu.open(e, () => );
}}
/>
)}
>
);
if (coverExpanded && img) return (
{i}
);
return (
{i}
SpotifyStore.openExternal(`/track/${track.id}`)}
>
{track.name}
by
{track.artists.map((a, i) => (
{a.name}
{i !== track.artists.length - 1 && {", "}}
))}
{track.album.name && (
on
{track.album.name}
)}
);
}
export function Player() {
const track = useStateFromStores(
[SpotifyStore],
() => SpotifyStore.track,
null,
(prev, next) => prev?.id === next?.id
);
const device = useStateFromStores(
[SpotifyStore],
() => SpotifyStore.device,
null,
(prev, next) => prev?.id === next?.id
);
const isPlaying = useStateFromStores([SpotifyStore], () => SpotifyStore.isPlaying);
const [shouldHide, setShouldHide] = React.useState(false);
// Hide player after 5 minutes of inactivity
// eslint-disable-next-line consistent-return
React.useEffect(() => {
setShouldHide(false);
if (!isPlaying) {
const timeout = setTimeout(() => setShouldHide(true), 1000 * 60 * 5);
return () => clearTimeout(timeout);
}
}, [isPlaying]);
if (!track || !device?.is_active || shouldHide)
return null;
return (
(
<>
Failed to render Spotify Modal :(
Check the console for errors
>
)}>
);
}