From e6be8ef1c9c30a7d54cafa5d7e2ac1b6c858036d Mon Sep 17 00:00:00 2001 From: Pihkaal Date: Mon, 22 Jan 2024 11:52:16 +0100 Subject: [PATCH] feat(music-player): implement static ui --- src/components/MusicPlayer.tsx | 106 +++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 src/components/MusicPlayer.tsx diff --git a/src/components/MusicPlayer.tsx b/src/components/MusicPlayer.tsx new file mode 100644 index 0000000..73dc4bf --- /dev/null +++ b/src/components/MusicPlayer.tsx @@ -0,0 +1,106 @@ +import { useState } from "react"; +import { useTerminal } from "~/context/TerminalContext"; +import { Text } from "./Text"; + +const formatDurationMSS = (duration: number) => { + const minutes = Math.floor(duration / 60); + const seconds = duration % 60; + + return `${minutes}:${seconds.toString().padStart(2, "0")}`; +}; + +export const MusicPlayer = (props: { + title: string; + artist: string; + album: string; + duration: number; + played: number; +}) => { + const terminal = useTerminal(); + + const [isPlaying, setIsPlaying] = useState(false); + setIsPlaying; + + const innerWidth = terminal.cols - 2; + + const timeString = `${formatDurationMSS(props.played)}/${formatDurationMSS( + props.duration, + )}`; + const barSize = Math.max( + 1, + Math.floor((props.played / props.duration) * innerWidth), + ); + + const beforeText_pos = innerWidth / 2 - timeString.length / 2; + const beforeText_filled = Math.min(barSize, beforeText_pos); + const beforeText_empty = beforeText_pos - beforeText_filled; + + const afterText_pos = innerWidth / 2 + timeString.length / 2; + const afterText_filled = Math.max( + 0, + Math.min(barSize, innerWidth - timeString.length) - afterText_pos, + ); + const afterText_empty = + innerWidth - afterText_pos - afterText_filled + 1 - (innerWidth % 2); + + return ( +

+ {/* Top bar */} + <> + + Playback + {"─".repeat(Math.max(0, innerWidth - 8))}┐ +
+ + + <> + + + {isPlaying ? "\udb81\udc0a" : "\udb80\udfe4"} {props.title} -{" "} + {props.artist} + + + {" ".repeat( + Math.max( + 0, + innerWidth - props.title.length - props.artist.length - 5, + ), + )} + │ + +
+ + + <> + + + {props.album} + {" ".repeat(innerWidth - props.album.length)} + + +
+ + + <> + + {" ".repeat(beforeText_filled)} + {" ".repeat(beforeText_empty)} + {timeString.split("").map((x, i) => ( + + {x} + + ))} + {" ".repeat(afterText_filled)} + {" ".repeat(afterText_empty)} + +
+ + + └{"─".repeat(innerWidth)}┘ +

+ ); +};