diff --git a/src/App.tsx b/src/App.tsx
index fe0f275..26825d0 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,10 +1,9 @@
import { BrowserRouter } from "react-router-dom";
-import { MusicPlayer } from "./components/MusicPlayer";
import { Kitty } from "./components/Kitty";
import { AppContextProvider } from "./context/AppContext";
import { Waybar } from "./components/Waybar/Waybar";
-import { MusicVisualizer } from "./components/MusicVisualizer";
import { useState } from "react";
+import { Music } from "./components/Music/Music";
function App() {
const [clicked, setClicked] = useState(false);
@@ -23,13 +22,7 @@ function App() {
-
-
-
-
-
-
-
+ {" "}
) : (
diff --git a/src/components/Music/Cava.tsx b/src/components/Music/Cava.tsx
new file mode 100644
index 0000000..3af57c3
--- /dev/null
+++ b/src/components/Music/Cava.tsx
@@ -0,0 +1,82 @@
+import { Fragment, useRef, useEffect, useState } from "react";
+import { ProgressBar, Group, useFrame, useTerminal } from "react-dom-curse";
+import { theme } from "~/utils/theme";
+
+export const Cava = () => {
+ const { width } = useTerminal();
+
+ const audioContext = useRef(new AudioContext());
+ const analyser = useRef(audioContext.current.createAnalyser());
+ const bufferLength = useRef(analyser.current.frequencyBinCount);
+ const dataArray = useRef(new Uint8Array(bufferLength.current));
+ const [barHeights, setBarHeights] = useState(
+ new Array(Math.round(width / 3)).fill(0),
+ );
+
+ useEffect(() => {
+ const audioElement = document.querySelector("audio");
+ if (!audioElement) return;
+
+ const audioSource =
+ audioContext.current.createMediaElementSource(audioElement);
+ audioSource.connect(analyser.current);
+ analyser.current.connect(audioContext.current.destination);
+ audioElement.play();
+
+ return () => {
+ audioSource.disconnect();
+ analyser.current.disconnect();
+ };
+ }, []);
+
+ useFrame(() => {
+ analyser.current.getByteFrequencyData(dataArray.current);
+
+ const barCount = Math.floor(width / 3);
+ const barHeights = [];
+
+ for (let i = 0; i < barCount; i++) {
+ const startIndex = Math.floor((i / barCount) * bufferLength.current);
+ const endIndex = Math.floor(((i + 1) / barCount) * bufferLength.current);
+ const slice = dataArray.current.slice(startIndex, endIndex);
+ const sum = slice.reduce((acc, val) => acc + val, 0);
+ const average = sum / slice.length;
+ barHeights.push(average);
+ }
+
+ setBarHeights(barHeights);
+ });
+
+ return (
+
+ {barHeights.map((height, x) => (
+
+
+
+
+ ))}
+
+ );
+};
diff --git a/src/components/Music/Music.tsx b/src/components/Music/Music.tsx
new file mode 100644
index 0000000..7c135c2
--- /dev/null
+++ b/src/components/Music/Music.tsx
@@ -0,0 +1,49 @@
+import { useEffect, useRef, useState } from "react";
+import { parseBlob, type IAudioMetadata } from "music-metadata-browser";
+
+import song from "/audio/colorful-flowers.mp3";
+import { Kitty } from "../Kitty";
+import { Cava } from "./Cava";
+import { SpotifyPlayer } from "./SpotifyPlayer";
+
+export const Music = () => {
+ const [metadata, setMetadata] = useState();
+ const [currentTime, setCurrentTime] = useState(0);
+ const audio = useRef(null);
+
+ const handleTimeUpdate = () => {
+ setCurrentTime(audio.current?.currentTime ?? 0);
+ };
+
+ useEffect(() => {
+ if (metadata) return;
+
+ void fetch(song)
+ .then(r => r.blob())
+ .then(b => parseBlob(b))
+ .then(setMetadata);
+ }, [metadata]);
+
+ return (
+ <>
+
+ {metadata && audio.current && (
+ <>
+
+
+
+
+
+
+
+ >
+ )}
+ >
+ );
+};
diff --git a/src/components/Music/SpotifyPlayer.tsx b/src/components/Music/SpotifyPlayer.tsx
new file mode 100644
index 0000000..bea63a7
--- /dev/null
+++ b/src/components/Music/SpotifyPlayer.tsx
@@ -0,0 +1,79 @@
+import { useEffect } from "react";
+import { Bar, Frame, Group, Text, useTerminal } from "react-dom-curse";
+import { theme } from "~/utils/theme";
+
+const formatDurationMSS = (duration: number) => {
+ duration = Math.floor(duration);
+
+ const minutes = Math.floor(duration / 60);
+ const seconds = duration % 60;
+
+ return `${minutes}:${seconds.toString().padStart(2, "0")}`;
+};
+
+export const SpotifyPlayer = (props: {
+ title: string;
+ artist: string;
+ album: string;
+ played: number;
+ duration: number;
+}) => {
+ const { width } = useTerminal();
+
+ const time = `${formatDurationMSS(props.played)}/${formatDurationMSS(
+ props.duration,
+ )}`;
+
+ return (
+
+
+
+ {props.title} · {props.artist}
+
+
+ {props.album}
+
+
+
+
+
+
+ {time}
+
+
+
+
+
+ {"Playback".substring(0, Math.min(8, width - 2))}
+
+
+ );
+};
diff --git a/src/components/MusicPlayer.tsx b/src/components/MusicPlayer.tsx
deleted file mode 100644
index cb937b6..0000000
--- a/src/components/MusicPlayer.tsx
+++ /dev/null
@@ -1,106 +0,0 @@
-import { useEffect, useRef, useState } from "react";
-import { Bar, Frame, Group, Text, useTerminal } from "react-dom-curse";
-import { theme } from "~/utils/theme";
-import { parseBlob, type IAudioMetadata } from "music-metadata-browser";
-
-import song from "/audio/colorful-flowers.mp3";
-
-const formatDurationMSS = (duration: number) => {
- duration = Math.floor(duration);
-
- const minutes = Math.floor(duration / 60);
- const seconds = duration % 60;
-
- return `${minutes}:${seconds.toString().padStart(2, "0")}`;
-};
-
-export const MusicPlayer = () => {
- const { width } = useTerminal();
- const [metadata, setMetadata] = useState();
-
- const audio = useRef();
- useEffect(() => {
- if (audio.current) return;
-
- audio.current = new Audio(song);
-
- void fetch(song)
- .then(r => r.blob())
- .then(b => parseBlob(b))
- .then(d => {
- void audio.current?.play();
- setMetadata(d);
- });
- }, []);
-
- if (!audio.current) return null;
-
- const played = audio.current.currentTime;
- const duration = audio.current.duration;
-
- const time = `${formatDurationMSS(played)}/${formatDurationMSS(duration)}`;
-
- return (
-
-
- {metadata ? (
- <>
-
- {metadata.common.title ?? "Unknown"} ·{" "}
- {metadata.common.artist ?? "Unknown"}
-
-
- {metadata.common.album ?? "Unknown"}
-
-
-
-
-
-
- {time}
-
-
- >
- ) : (
- <>
-
- No playback found.
-
- >
- )}
-
-
-
- {"Playback".substring(0, Math.min(8, width - 2))}
-
-
- );
-};
diff --git a/src/components/MusicVisualizer.tsx b/src/components/MusicVisualizer.tsx
deleted file mode 100644
index 6a3f5c3..0000000
--- a/src/components/MusicVisualizer.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { type FunctionComponent } from "react";
-
-export const MusicVisualizer: FunctionComponent = () => (
-
-);