From 1e90ecf8268197d3cb81a48c49bce016d322b1d8 Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Thu, 12 May 2022 18:48:40 +0200 Subject: [PATCH] Spotify container --- package-lock.json | 30 +++++++++++++++++ package.json | 3 +- src/components/Spotify.tsx | 42 ++++++++++++++++++++---- src/lib/interfaces.ts | 9 ++--- src/styles/containers/Spotify.module.css | 21 ++++++++++-- src/styles/global.css | 17 ++++++---- 6 files changed, 102 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index f8b0f62..ab214e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "GPL-3.0-only", "dependencies": { "buffer": "^6.0.3", + "fast-average-color": "^7.1.0", "fast-xml-parser": "^4.0.0-beta.8", "gatsby": "^4.4.0", "gatsby-plugin-react-svg": "^3.1.0", @@ -2767,6 +2768,11 @@ "node": ">= 6" } }, + "node_modules/@types/offscreencanvas": { + "version": "2019.6.4", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.6.4.tgz", + "integrity": "sha512-u8SAgdZ8ROtkTF+mfZGOscl0or6BSj9A4g37e6nvxDc+YB/oDut0wHkK2PBBiC2bNR8TS0CPV+1gAk4fNisr1Q==" + }, "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -7475,6 +7481,17 @@ "url": "https://github.com/sponsors/jaydenseric" } }, + "node_modules/fast-average-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/fast-average-color/-/fast-average-color-7.1.0.tgz", + "integrity": "sha512-eTc18sdbr2P2xZFMhvWmo+T7MJ403k4jSiapTMoOcvkptu7SWOU+TzN4tFL4B9sIKUSXA63Xu7Mpc4fmncDZ+Q==", + "dependencies": { + "@types/offscreencanvas": "^2019.6.4" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/fast-copy": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-2.1.1.tgz", @@ -18909,6 +18926,11 @@ } } }, + "@types/offscreencanvas": { + "version": "2019.6.4", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.6.4.tgz", + "integrity": "sha512-u8SAgdZ8ROtkTF+mfZGOscl0or6BSj9A4g37e6nvxDc+YB/oDut0wHkK2PBBiC2bNR8TS0CPV+1gAk4fNisr1Q==" + }, "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -22482,6 +22504,14 @@ "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz", "integrity": "sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==" }, + "fast-average-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/fast-average-color/-/fast-average-color-7.1.0.tgz", + "integrity": "sha512-eTc18sdbr2P2xZFMhvWmo+T7MJ403k4jSiapTMoOcvkptu7SWOU+TzN4tFL4B9sIKUSXA63Xu7Mpc4fmncDZ+Q==", + "requires": { + "@types/offscreencanvas": "^2019.6.4" + } + }, "fast-copy": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-2.1.1.tgz", diff --git a/package.json b/package.json index 7693c01..1611116 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ }, "dependencies": { "buffer": "^6.0.3", + "fast-average-color": "^7.1.0", "fast-xml-parser": "^4.0.0-beta.8", "gatsby": "^4.4.0", "gatsby-plugin-react-svg": "^3.1.0", @@ -38,4 +39,4 @@ "devDependencies": { "@types/webpack-env": "^1.16.3" } -} \ No newline at end of file +} diff --git a/src/components/Spotify.tsx b/src/components/Spotify.tsx index 4e06509..bd424b7 100644 --- a/src/components/Spotify.tsx +++ b/src/components/Spotify.tsx @@ -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(undefined) + const [lastSongInfo, setLastSongInfo] = React.useState({ + 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
- + return
+ {lastSongInfo.cover ? Cover :
} +
+ {lastSongInfo.title || "Unbekannt"}
+ {lastSongInfo.artist ? lastSongInfo.artist.join(", ") || "Unbekannt" : "Unbekannt"}
+ {lastSongInfo.album || "Unbekannt"} +
+
} diff --git a/src/lib/interfaces.ts b/src/lib/interfaces.ts index 99eb142..a8909c7 100644 --- a/src/lib/interfaces.ts +++ b/src/lib/interfaces.ts @@ -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; } \ No newline at end of file diff --git a/src/styles/containers/Spotify.module.css b/src/styles/containers/Spotify.module.css index d08032b..0531709 100644 --- a/src/styles/containers/Spotify.module.css +++ b/src/styles/containers/Spotify.module.css @@ -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; } \ No newline at end of file diff --git a/src/styles/global.css b/src/styles/global.css index e9b5dfb..096a619 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -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 {