improve BackgroundMediaPlayer

This commit is contained in:
SrGooglo 2023-04-04 23:51:31 +00:00
parent 8a53daa3fa
commit dedbe3d368
2 changed files with 326 additions and 137 deletions

View File

@ -1,123 +1,49 @@
import React from "react"
import Ticker from "react-ticker"
import { FastAverageColor } from "fast-average-color"
import * as antd from "antd"
import classnames from "classnames"
import { Icons } from "components/Icons"
import Marquee from "react-fast-marquee"
import "./index.less"
const useEventBus = (events) => {
const registerEvents = () => {
for (const [event, handler] of Object.entries(events)) {
app.eventBus.on(event, handler)
}
function RGBStringToValues(rgbString) {
if (!rgbString) {
return [0, 0, 0]
}
const unregisterEvents = () => {
for (const [event, handler] of Object.entries(events)) {
app.eventBus.off(event, handler)
}
}
const rgb = rgbString.replace("rgb(", "").replace(")", "").split(",").map((v) => parseInt(v))
React.useEffect(() => {
registerEvents()
return () => {
unregisterEvents()
}
}, [])
}
const fac = new FastAverageColor()
const bruh = (props) => {
const [thumbnailAnalysis, setThumbnailAnalysis] = React.useState("#000000")
const [currentPlaying, setCurrentPlaying] = React.useState(app.cores.player.getState("currentAudioManifest"))
const [plabackState, setPlaybackState] = React.useState(app.cores.player.getState("playbackStatus") ?? "stopped")
const onClickMinimize = () => {
app.cores.player.minimize()
}
const calculateAverageCoverColor = async () => {
if (currentPlaying) {
const color = await fac.getColorAsync(currentPlaying.thumbnail)
setThumbnailAnalysis(color)
updateBackgroundItem(color)
}
}
const updateBackgroundItem = () => {
app.SidebarController.updateBackgroundItem(undefined, {
icon: <Icons.MdMusicNote />,
style: {
backgroundColor: thumbnailAnalysis?.hex
}
})
}
useEventBus({
"player.current.update": (data) => {
console.log("player.current.update", data)
setCurrentPlaying(data)
updateBackgroundItem()
},
"player.playback.update": (data) => {
setPlaybackState(data)
updateBackgroundItem()
}
})
React.useEffect(() => {
calculateAverageCoverColor()
}, [currentPlaying])
React.useEffect(() => {
}, [])
return <div
className="background_media_player"
onClick={onClickMinimize}
>
{
currentPlaying && <div
className={classnames(
"background_media_player__title",
{
["lightBackground"]: thumbnailAnalysis.isLight,
}
)}
>
<h4>
{currentPlaying.title} - {currentPlaying.artist}
</h4>
</div>
}
</div>
return [rgb[0], rgb[1], rgb[2]]
}
export default class BackgroundMediaPlayer extends React.Component {
state = {
thumbnailAnalysis: null,
thumbnailAnalysis: app.cores.player.getState("coverColorAnalysis"),
currentPlaying: app.cores.player.getState("currentAudioManifest"),
plabackState: app.cores.player.getState("playbackStatus") ?? "stopped",
expanded: false,
}
events = {
"player.coverColorAnalysis.update": (data) => {
this.setState({
thumbnailAnalysis: data
})
},
"player.current.update": (data) => {
this.calculateAverageCoverColor()
this.setState({
currentPlaying: data
})
},
"player.playback.update": (data) => {
this.updateBackgroundItem()
"player.status.update": (data) => {
this.setState({
plabackState: data
})
},
"sidebar.expanded": (to) => {
if (!to) {
this.toogleExpand(false)
}
}
}
@ -125,30 +51,17 @@ export default class BackgroundMediaPlayer extends React.Component {
app.cores.player.minimize()
}
calculateAverageCoverColor = async () => {
if (this.state.currentPlaying) {
const color = await fac.getColorAsync(this.state.currentPlaying.thumbnail)
this.setState({
thumbnailAnalysis: color
})
this.updateBackgroundItem(color)
toogleExpand = (to) => {
if (typeof to !== "boolean") {
to = !this.state.expanded
}
}
updateBackgroundItem = (analysis) => {
app.SidebarController.updateBackgroundItem(undefined, {
icon: <Icons.MdMusicNote />,
style: {
backgroundColor: analysis?.hex ?? this.state.thumbnailAnalysis?.hex,
}
this.setState({
expanded: to
})
}
componentDidMount = async () => {
this.calculateAverageCoverColor()
for (const [event, handler] of Object.entries(this.events)) {
app.eventBus.on(event, handler)
}
@ -161,24 +74,113 @@ export default class BackgroundMediaPlayer extends React.Component {
}
render() {
return <div
className="background_media_player"
onClick={this.onClickMinimize}
return <li
className={classnames(
"background_media_player",
{
["lightBackground"]: this.state.thumbnailAnalysis?.isLight,
["expanded"]: this.state.expanded,
}
)}
style={{
backgroundColor: this.state.thumbnailAnalysis?.rgba,
"--averageColorValues": this.state.thumbnailAnalysis?.rgba,
}}
>
{
this.state.currentPlaying && <div
<div
className="background_media_player__background"
style={{
backgroundImage: `url(${this.state.currentPlaying?.thumbnail})`
}}
/>
<div
className="background_media_player__row"
onClick={this.toogleExpand}
>
<div
id="sidebar_item_icon"
className={classnames(
"background_media_player__title",
"background_media_player__icon",
{
["lightBackground"]: this.state.thumbnailAnalysis?.isLight,
["bounce"]: this.state.plabackState === "playing",
}
)}
>
<h4>
{this.state.currentPlaying?.title} - {this.state.currentPlaying?.artist}
</h4>
{
this.state.plabackState === "playing" ? <Icons.MdMusicNote /> : <Icons.MdPause />
}
</div>
}
</div>
<div
id="sidebar_item_content"
className="background_media_player__title"
>
{
!this.state.expanded && <Marquee
gradientColor={RGBStringToValues(this.state.thumbnailAnalysis?.rgb)}
gradientWidth={20}
play={this.state.plabackState !== "stopped"}
>
<h4>
{
this.state.plabackState === "stopped" ? "Nothing is playing" : (this.state.currentPlaying?.title ?? "Untitled")
}
</h4>
</Marquee>
}
{
this.state.expanded && <h4>
<Icons.MdAlbum />
{
this.state.plabackState === "stopped" ? "Nothing is playing" : (this.state.currentPlaying?.title ?? "Untitled")
}
</h4>
}
</div>
</div>
<div
className={classnames(
"background_media_player__row",
"background_media_player__controls",
{
["hidden"]: !this.state.expanded,
}
)}
>
<antd.Button
size="small"
shape="rounded"
type="ghost"
icon={<Icons.ChevronLeft />}
onClick={app.cores.player.playback.previous}
/>
<antd.Button
size="small"
type="ghost"
shape="circle"
icon={this.state.plabackState === "playing" ? <Icons.MdPause /> : <Icons.MdPlayArrow />}
onClick={app.cores.player.playback.toogle}
/>
<antd.Button
size="small"
shape="rounded"
type="ghost"
icon={<Icons.ChevronRight />}
onClick={app.cores.player.playback.next}
/>
<antd.Button
size="small"
shape="rounded"
type="ghost"
icon={<Icons.Minimize />}
onClick={this.onClickMinimize}
/>
</div>
</li>
}
}

View File

@ -1,36 +1,223 @@
.background_media_player {
overflow: hidden;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 40px;
padding: 10px;
overflow: hidden;
border-radius: 12px;
transition: all 150ms ease-in-out;
.background_media_player__title {
overflow: hidden;
line-height: 40px;
white-space: nowrap;
color: var(--text-color-white);
width: 100%;
background-repeat: no-repeat;
background-size: cover;
&.expanded {
height: 120px;
.background_media_player__background {
opacity: 0.4;
}
.background_media_player__icon {
width: 0;
opacity: 0;
}
.background_media_player__title {
padding: 10px 0;
h4 {
word-break: break-all;
word-wrap: break-word;
white-space: break-spaces;
font-size: 1rem;
}
}
.background_media_player__controls {
margin-top: 10px;
background-color: var(--text-color-white);
}
}
&.lightBackground {
color: var(--text-color-black);
.background_media_player__icon {
svg {
color: var(--text-color-black);
}
}
.background_media_player__title {
color: var(--text-color-black);
&.lightBackground {
h4 {
color: var(--text-color-black);
}
}
h4 {
font-size: 1rem;
font-weight: 600;
.background_media_player__controls {
color: var(--text-color-black);
overflow: hidden;
.ant-btn {
color: var(--text-color-black);
text-overflow: ellipsis;
white-space: nowrap;
svg {
color: var(--text-color-black);
}
}
}
}
font-family: "Space Grotesk", sans-serif;
.background_media_player__background {
pointer-events: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 12px;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
transition: all 150ms ease-in-out;
opacity: 0;
}
.background_media_player__row {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
z-index: 350;
width: 100%;
&.hidden {
pointer-events: none;
opacity: 0;
height: 0;
}
}
.background_media_player__icon {
svg {
margin-right: 0 !important;
color: var(--text-color-white);
}
&.bounce {
animation: bounce 1s infinite;
}
}
.background_media_player__title {
max-height: 67px;
transition: all 150ms ease-in-out;
color: var(--text-color-white);
width: 100%;
overflow: hidden;
h4 {
line-height: 20px;
font-size: 0.8rem;
font-weight: 600;
margin: 0 0 0 10px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-family: "Space Grotesk", sans-serif;
color: var(--text-color-white);
}
.marquee-container {
width: 100%;
.overlay {
width: 100%;
}
}
}
.background_media_player__controls {
display: flex;
flex-direction: row;
align-self: flex-end;
align-items: center;
justify-content: space-evenly;
width: 100%;
color: var(--text-color-white);
background-color: var(--text-color-black);
border-radius: 12px;
opacity: 0.5;
.ant-btn {
color: var(--text-color-black);
background-color: transparent;
svg {
color: var(--text-color-black);
}
}
}
}
@keyframes bounce {
0%,
20%,
50%,
80%,
100% {
transform: translateY(0);
}
40% {
transform: translateY(-5px);
}
60% {
transform: translateY(-3px);
}
}