diff --git a/packages/app/src/components/Player/Controls/index.jsx b/packages/app/src/components/Player/Controls/index.jsx index 3e151ff3..64c74bdf 100755 --- a/packages/app/src/components/Player/Controls/index.jsx +++ b/packages/app/src/components/Player/Controls/index.jsx @@ -30,7 +30,13 @@ const EventsHandlers = { return app.cores.player.controls.mute("toggle") }, "like": async (ctx) => { - await app.cores.player.toggleCurrentTrackLike(!ctx.track_manifest?.liked) + if (!ctx.track_manifest) { + return false + } + + const track = app.cores.player.track() + + return await track.manifest.serviceOperations.toggleItemFavourite("track", ctx.track_manifest._id) }, } @@ -84,12 +90,6 @@ const Controls = (props) => { onClick={() => handleAction("next")} disabled={playerState.control_locked} /> - { - app.isMobile && handleAction("like")} - liked={playerState.track_manifest?.liked} - /> - } { !app.isMobile && { } + + { + app.isMobile && handleAction("like")} + /> + } } diff --git a/packages/app/src/components/Player/ExtraActions/index.jsx b/packages/app/src/components/Player/ExtraActions/index.jsx index 4e307f97..d4dd7be6 100755 --- a/packages/app/src/components/Player/ExtraActions/index.jsx +++ b/packages/app/src/components/Player/ExtraActions/index.jsx @@ -6,12 +6,18 @@ import LikeButton from "@components/LikeButton" import { usePlayerStateContext } from "@contexts/WithPlayerContext" -import MusicModel from "@models/music" - const ExtraActions = (props) => { const [playerState] = usePlayerStateContext() + const handleClickLike = async () => { - await MusicModel.toggleItemFavourite("track", playerState.track_manifest._id) + if (!playerState.track_manifest) { + console.error("Cannot like a track if nothing is playing") + return false + } + + const track = app.cores.player.track() + + await track.manifest.serviceOperations.toggleItemFavourite("track", playerState.track_manifest._id) } return
@@ -24,8 +30,8 @@ const ExtraActions = (props) => { } { - !app.isMobile && } diff --git a/packages/app/src/components/Player/SeekBar/index.jsx b/packages/app/src/components/Player/SeekBar/index.jsx index ab0aff42..b1165bcd 100755 --- a/packages/app/src/components/Player/SeekBar/index.jsx +++ b/packages/app/src/components/Player/SeekBar/index.jsx @@ -118,6 +118,9 @@ export default class SeekBar extends React.Component { this.calculateTime() this.updateAll() }, + "player.durationchange": () => { + this.calculateDuration() + }, } tick = () => { diff --git a/packages/app/src/components/Player/ToolBarPlayer/index.jsx b/packages/app/src/components/Player/ToolBarPlayer/index.jsx index 0469f5a4..24857a36 100755 --- a/packages/app/src/components/Player/ToolBarPlayer/index.jsx +++ b/packages/app/src/components/Player/ToolBarPlayer/index.jsx @@ -15,195 +15,215 @@ import ExtraActions from "../ExtraActions" import "./index.less" function isOverflown(parent, element) { - if (!parent || !element) { - return false - } + if (!parent || !element) { + return false + } - const parentRect = parent.getBoundingClientRect() - const elementRect = element.getBoundingClientRect() + const parentRect = parent.getBoundingClientRect() + const elementRect = element.getBoundingClientRect() - return elementRect.width > parentRect.width + return elementRect.width > parentRect.width +} + +const Indicators = (props) => { + const { track } = props + + if (!track) { + return null + } + + const indicators = [] + + if (track.metadata) { + if (track.metadata.lossless) { + indicators.push() + } + } + + if (indicators.length === 0) { + return null + } + + return ( +
+
{indicators}
+
+ ) } const ServiceIndicator = (props) => { - if (!props.service) { - return null - } + if (!props.service) { + return null + } - switch (props.service) { - case "tidal": { - return
- -
- } - default: { - return null - } - } + switch (props.service) { + case "tidal": { + return ( +
+ +
+ ) + } + default: { + return null + } + } } const Player = (props) => { - const [playerState] = usePlayerStateContext() + const [playerState] = usePlayerStateContext() - const contentRef = React.useRef() - const titleRef = React.useRef() - const subtitleRef = React.useRef() + const contentRef = React.useRef() + const titleRef = React.useRef() - const [topActionsVisible, setTopActionsVisible] = React.useState(false) - const [titleOverflown, setTitleOverflown] = React.useState(false) - const [subtitleOverflown, setSubtitleOverflown] = React.useState(false) + const [topActionsVisible, setTopActionsVisible] = React.useState(false) + const [titleOverflown, setTitleOverflown] = React.useState(false) + const [coverAnalysis, setCoverAnalysis] = React.useState(null) - const handleOnMouseInteraction = (e) => { - if (e.type === "mouseenter") { - setTopActionsVisible(true) - } else { - setTopActionsVisible(false) - } - } + const handleOnMouseInteraction = (e) => { + if (e.type === "mouseenter") { + setTopActionsVisible(true) + } else { + setTopActionsVisible(false) + } + } - const { - title, - album, - artistStr, - liked, - service, - lyrics_enabled, - cover_analysis, - cover, - } = playerState.track_manifest ?? {} + const { title, artistStr, service, cover_analysis, cover } = + playerState.track_manifest ?? {} - const playing = playerState.playback_status === "playing" - const stopped = playerState.playback_status === "stopped" + const playing = playerState.playback_status === "playing" + const stopped = playerState.playback_status === "stopped" - const titleText = (!playing && stopped) ? "Stopped" : (title ?? "Untitled") - const subtitleText = "" + const titleText = !playing && stopped ? "Stopped" : (title ?? "Untitled") + const subtitleText = "" - React.useEffect(() => { - const titleIsOverflown = isOverflown(contentRef.current, titleRef.current) + React.useEffect(() => { + const titleIsOverflown = isOverflown( + contentRef.current, + titleRef.current, + ) - setTitleOverflown(titleIsOverflown) - }, [title]) + setTitleOverflown(titleIsOverflown) + }, [title]) - return
-
- { - !playerState.control_locked && } - shape="circle" + React.useEffect(() => { + const trackInstance = app.cores.player.track() - /> - } + if (playerState.track_manifest && trackInstance) { + if ( + typeof trackInstance.manifest.analyzeCoverColor === "function" + ) { + trackInstance.manifest + .analyzeCoverColor() + .then((analysis) => { + setCoverAnalysis(analysis) + }) + .catch((err) => { + console.error("Failed to get cover analysis", err) + }) + } + } + }, [playerState.track_manifest]) - { - lyrics_enabled && } - shape="circle" - onClick={() => app.location.push("/lyrics")} - /> - } + return ( +
+
+ {!playerState.control_locked && ( + } shape="circle" /> + )} - {/* } + shape="circle" + onClick={() => app.location.push("/lyrics")} + /> + + {/* } > HyperDrive */} - } - shape="circle" - onClick={() => app.cores.player.close()} - /> -
-
-
+ } + shape="circle" + onClick={() => app.cores.player.close()} + /> +
+
+
-
-
-

- +
+
+

+ - {titleText} -

+ {titleText} +

- { - titleOverflown && -

- + {titleOverflown && ( + +

+ - {titleText} -

-
- } + {titleText} +

+
+ )} -

- {artistStr ?? ""} -

-
+

+ {artistStr ?? ""} +

+
-
- +
+ - + - -
-
-
-
+ +
+ + +
+
+
+ ) } -export default Player \ No newline at end of file +export default Player diff --git a/packages/app/src/components/Player/ToolBarPlayer/index.less b/packages/app/src/components/Player/ToolBarPlayer/index.less index c2b43048..18f863a0 100755 --- a/packages/app/src/components/Player/ToolBarPlayer/index.less +++ b/packages/app/src/components/Player/ToolBarPlayer/index.less @@ -266,4 +266,40 @@ .ant-btn { padding: 0; } +} + +.toolbar_player_indicators_wrapper { + position: absolute; + + bottom: 0; + left: 0; + + padding: 10px; + + + .toolbar_player_indicators { + display: flex; + flex-direction: row; + + justify-content: space-between; + align-items: center; + + width: fit-content; + + padding: 7px 10px; + + border-radius: 12px; + + background-color: rgba(var(--layoutBackgroundColor), 0.7); + -webkit-backdrop-filter: blur(5px); + backdrop-filter: blur(5px); + + font-size: 1rem; + + svg { + margin: 0 !important; + + color: white + } + } } \ No newline at end of file