Refactor mobile player to use new player core

This commit is contained in:
SrGooglo 2025-04-24 06:14:13 +00:00
parent 74021f38b6
commit 6e80fc67fa
2 changed files with 208 additions and 229 deletions

View File

@ -4,7 +4,7 @@ import classnames from "classnames"
import { Icons } from "@components/Icons" import { Icons } from "@components/Icons"
import SeekBar from "@components/Player/SeekBar" import SeekBar from "@components/Player/SeekBar"
import Controls from "@components/Player/Controls" import Controls from "@components/Player/Controls"
import ExtraActions from "@components/Player/ExtraActions" import Actions from "@components/Player/Actions"
import { usePlayerStateContext } from "@contexts/WithPlayerContext" import { usePlayerStateContext } from "@contexts/WithPlayerContext"
import RGBStringToValues from "@utils/rgbToValues" import RGBStringToValues from "@utils/rgbToValues"
@ -12,102 +12,96 @@ import RGBStringToValues from "@utils/rgbToValues"
import "./index.less" import "./index.less"
const ServiceIndicator = (props) => { const ServiceIndicator = (props) => {
if (!props.service) { if (!props.service) {
return null return null
} }
switch (props.service) { switch (props.service) {
case "tidal": { case "tidal": {
return <div className="service_indicator"> return (
<Icons.SiTidal /> Playing from Tidal <div className="service_indicator">
</div> <Icons.SiTidal /> Playing from Tidal
} </div>
default: { )
return null }
} default: {
} return null
}
}
} }
const AudioPlayer = (props) => { const AudioPlayer = (props) => {
const [playerState] = usePlayerStateContext() const [playerState] = usePlayerStateContext()
React.useEffect(() => { React.useEffect(() => {
if (app.currentDragger) { if (app.currentDragger) {
app.currentDragger.setBackgroundColorValues(RGBStringToValues(playerState.track_manifest?.cover_analysis?.rgb)) app.currentDragger.setBackgroundColorValues(
} RGBStringToValues(
playerState.track_manifest?.cover_analysis?.rgb,
),
)
}
}, [playerState.track_manifest?.cover_analysis])
}, [playerState.track_manifest?.cover_analysis]) const {
title,
album,
artist,
service,
lyricsEnabled,
cover_analysis,
cover,
} = playerState.track_manifest ?? {}
const { const playing = playerState.playback_status === "playing"
title, const stopped = playerState.playback_status === "stopped"
album,
artist,
service,
lyricsEnabled,
cover_analysis,
cover,
} = playerState.track_manifest ?? {}
const playing = playerState.playback_status === "playing" const titleText = !playing && stopped ? "Stopped" : (title ?? "Untitled")
const stopped = playerState.playback_status === "stopped" const subtitleText = `${artist} | ${album?.title ?? album}`
const titleText = (!playing && stopped) ? "Stopped" : (title ?? "Untitled") return (
const subtitleText = `${artist} | ${album?.title ?? album}` <div
className={classnames("mobile-player_wrapper", {
cover_light: cover_analysis?.isLight,
})}
style={{
"--cover_isLight": cover_analysis?.isLight,
}}
>
<div className="mobile-player">
<ServiceIndicator service={service} />
return <div <div
className={classnames( className="mobile-player-cover"
"mobile_media_player_wrapper", style={{
{ backgroundImage: `url(${cover ?? "/assets/no_song.png"})`,
"cover_light": cover_analysis?.isLight, }}
} />
)}
style={{
"--cover_isLight": cover_analysis?.isLight,
}}
>
<div className="mobile_media_player">
<ServiceIndicator
service={service}
/>
<div <div className="mobile-player-header">
className="cover" <div className="mobile-player-info">
style={{ <div className="mobile-player-info-title">
backgroundImage: `url(${cover ?? "/assets/no_song.png"})`, <h1>{titleText}</h1>
}} </div>
/> <div className="mobile-player-info-subTitle">
<span>{subtitleText}</span>
</div>
</div>
</div>
<div className="header"> <Controls />
<div className="info">
<div className="title">
<h2>
{
titleText
}
</h2>
</div>
<div className="subTitle">
<div className="artist">
<h3>
{subtitleText}
</h3>
</div>
</div>
</div>
</div>
<Controls /> <SeekBar
stopped={playerState.playback_status === "stopped"}
playing={playerState.playback_status === "playing"}
streamMode={playerState.livestream_mode}
disabled={playerState.control_locked}
/>
<SeekBar <Actions />
stopped={playerState.playback_status === "stopped"} </div>
playing={playerState.playback_status === "playing"} </div>
streamMode={playerState.livestream_mode} )
disabled={playerState.control_locked}
/>
<ExtraActions />
</div>
</div>
} }
export default AudioPlayer export default AudioPlayer

View File

@ -1,199 +1,184 @@
@top_controls_height: 55px; @top_controls_height: 55px;
.mobile_media_player_wrapper { .mobile-player_wrapper {
position: relative; position: relative;
z-index: 320; z-index: 320;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
width: 100%; width: 100%;
.mobile_media_player_background { margin-bottom: 30px;
position: absolute;
z-index: 320; .mobile-player_background {
position: absolute;
top: 0; z-index: 320;
left: 0;
width: 100%; top: 0;
height: 100%; left: 0;
background-color: rgba(var(--cover_averageValues), 0.4); width: 100%;
} height: 100%;
background-color: rgba(var(--cover_averageValues), 0.4);
}
} }
.mobile_media_player { .mobile-player {
position: relative; position: relative;
display: inline-flex; display: inline-flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
justify-content: center; justify-content: center;
width: 100%; width: 100%;
height: 100%; height: 100%;
gap: 10px; gap: 10px;
transition: all 150ms ease-out; transition: all 150ms ease-out;
z-index: 330; z-index: 330;
.service_indicator { .service_indicator {
color: var(--text-color); color: var(--text-color);
background-color: var(--background-color-accent); background-color: var(--background-color-accent);
padding: 7px; padding: 7px;
border-radius: 8px; border-radius: 8px;
font-size: 0.9rem; font-size: 0.9rem;
} }
.cover { .mobile-player-cover {
position: relative; position: relative;
z-index: 320; z-index: 320;
margin: auto; margin: auto;
width: 100%; width: 100%;
height: 100%; height: 100%;
min-height: 40vh; min-height: 40vh;
min-width: 100%; min-width: 100%;
border-radius: 24px; border-radius: 24px;
background-position: center; background-position: center;
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
object-position: center; object-position: center;
} }
} }
.header { .mobile-player-header {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
width: 100%; width: 100%;
.info { .mobile-player-info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
h1, h1,
h2, h2,
h3, h3,
h4, h4,
h5, h5,
h6, h6,
p, p,
span { span {
margin: 0; margin: 0;
color: var(--text-color); color: var(--text-color);
} }
width: 100%; width: 100%;
.title { .mobile-player-info-title {
font-size: 1rem; display: flex;
font-weight: 600; flex-direction: row;
color: var(--text-color);
word-break: break-all; align-items: center;
font-family: "Space Grotesk", sans-serif; font-size: 1rem;
} font-weight: 600;
.subTitle { word-break: break-all;
display: flex;
flex-direction: row;
width: 100%; font-family: "Space Grotesk", sans-serif;
}
justify-content: space-between; .mobile-player-info-subTitle {
display: flex;
flex-direction: row;
.likeButton { align-items: center;
margin-right: 20px; justify-content: space-between;
}
.artist { font-size: 0.7rem;
font-size: 0.6rem; font-weight: 400;
font-weight: 400; }
color: var(--text-color); }
} }
}
}
}
.player-controls { .player-controls {
.ant-btn { .ant-btn {
min-width: 40px !important; min-width: 40px !important;
min-height: 40px !important; min-height: 40px !important;
} }
svg { svg {
font-size: 1.2rem; font-size: 1.2rem;
} }
.playButton { .playButton {
min-width: 50px !important; min-width: 50px !important;
min-height: 50px !important; min-height: 50px !important;
svg { svg {
font-size: 1.6rem; font-size: 1.6rem;
} }
} }
} }
.player-seek_bar { .player-seek_bar {
.progress { .progress {
.MuiSlider-root { .MuiSlider-root {
.MuiSlider-rail { .MuiSlider-rail {
height: 7px; height: 7px;
} }
.MuiSlider-track { .MuiSlider-track {
height: 7px; height: 7px;
} }
.MuiSlider-thumb { .MuiSlider-thumb {
width: 5px; width: 5px;
height: 13px; height: 13px;
border-radius: 2px; border-radius: 2px;
background-color: var(--background-color-contrast); background-color: var(--background-color-contrast);
} }
} }
} }
} }
}
.extra_actions {
padding: 0 30px;
.ant-btn {
padding: 5px;
svg {
height: 23px;
min-width: 23px;
}
}
}
}