Spotify container

This commit is contained in:
2022-05-12 18:48:40 +02:00
parent a1300e851d
commit 1e90ecf826
6 changed files with 102 additions and 20 deletions

View File

@ -1,16 +1,22 @@
import * as React from "react"
//import useWebSocket from "react-use-websocket";
import { connect } from "mqtt"
import FastAverageColor from 'fast-average-color';
import type { SecretsMQTT, SongInfo } from "../lib/interfaces"
import * as styles from "../styles/containers/Spotify.module.css"
const fac = new FastAverageColor();
const Spotify = ({ mqtt, Alternative }: { mqtt: SecretsMQTT, Alternative: any }) => {
const [lastSongInfo, setLastSongInfo] = React.useState<SongInfo | undefined>(undefined)
const [lastSongInfo, setLastSongInfo] = React.useState<SongInfo>({
playbackState: "STOPPED"
});
const [color, setColors] = React.useState<{bg?: string; text?: string}>({});
const handleMessage = (_topic: string, message: string) => {
try {
const songInfo: SongInfo = JSON.parse(message.toString());
setLastSongInfo(songInfo);
setLastSongInfo((lastInfo) => {return {...lastInfo, ...songInfo}});
} catch {
console.warn(`Can't parse song info: ${message.toString()}`);
}
@ -20,7 +26,7 @@ const Spotify = ({ mqtt, Alternative }: { mqtt: SecretsMQTT, Alternative: any })
const client = connect(mqtt.url, {
username: mqtt.username,
password: mqtt.password,
protocol: "mqtt"
protocol: "ws"
});
client.on("message", handleMessage);
@ -34,12 +40,36 @@ const Spotify = ({ mqtt, Alternative }: { mqtt: SecretsMQTT, Alternative: any })
return () => { client.end() }
}, [])
if (true || !lastSongInfo || lastSongInfo.playbackState !== "PLAYING") {
React.useEffect(() => {
(async () => {
if (lastSongInfo.playbackState !== "STOPPED" && lastSongInfo.cover && lastSongInfo.cover.startsWith("http") && document) {
const { value, isDark } = await fac.getColorAsync(lastSongInfo.cover);
value[3] = 0.8;
setColors({
bg: `rgba(${value.join(",")})`,
text: `var(--textColor${isDark ? "Light" : "Dark"})`
});
} else {
setColors({});
}
})();
}, [lastSongInfo]);
if (lastSongInfo.playbackState === "STOPPED") {
return Alternative;
}
return <div className={`container ${styles.container}`}>
return <div className={`container ${styles.container}`} style={{
background: color.bg,
color: color.text
}}>
{lastSongInfo.cover ? <img src={lastSongInfo.cover} alt="Cover" className={styles.cover} /> : <div></div>}
<div className={styles.meta}>
<span className={styles.title}>{lastSongInfo.title || "Unbekannt"}</span><br/>
<span>{lastSongInfo.artist ? lastSongInfo.artist.join(", ") || "Unbekannt" : "Unbekannt"}</span><br/>
<span>{lastSongInfo.album || "Unbekannt"}</span>
</div>
</div>
}

View File

@ -72,9 +72,10 @@ export interface PlantState {
}
}
export interface SongInfo {
export type SongInfo = {
playbackState: "PLAYING" | "PAUSE" | "STOPPED";
title: string;
artists: string[];
album: string;
title?: string;
artist?: string[];
album?: string;
cover?: string;
}

View File

@ -6,16 +6,31 @@
width:100%;
height:100%;
padding:5px;
background: var(--spotifyColor);
background: var(--containerBg);
border-radius: 5px;
}
.container p {
.meta {
max-width: 21vw;
color: inherit;
word-wrap: normal;
padding: 5px 15px;
height:min-content;
margin: auto 0;
font-size: larger;
}
.meta span:not(:first-child) {
margin-top: 5px;
display: inline-block;
}
.title {
font-size: 180%;
font-size: 170%;
font-weight: bold;
color: inherit;
max-height: calc((19vh - 10px) / 2);
display: inline-block;
overflow-y: hidden;
}
.cover {
height: calc(19vh - 10px);
border-radius: 5px;
}

View File

@ -4,17 +4,22 @@
box-sizing: border-box;
}
:root {
--textColorLight: #b0b0b0;
--textColorDark: #000000;
}
:root, :root[data-theme="day"] {
--containerBg: rgba(255,255,255,0.5);
--textColor: #000000;
color: #000000;
--iconColor: #000000;
--textColor: var(--textColorDark);
color: var(--textColorDark);
--iconColor: var(--textColorDark);
}
:root[data-theme="night"] {
--containerBg: rgba(20,20,20,0.8);
--textColor: #b0b0b0;
color: #b0b0b0;
--iconColor: #b0b0b0;
--textColor: var(--textColorLight);
color: var(--textColorLight);
--iconColor: var(--textColorLight);
}
body, main {