mirror of
https://github.com/ragestudio/comty.git
synced 2025-07-08 08:44:15 +00:00
Refactor Track menu logic into separate handlers and items files
This commit is contained in:
parent
d1b58d19fc
commit
843405dd15
@ -1,9 +1,10 @@
|
||||
import React from "react"
|
||||
import * as antd from "antd"
|
||||
import classnames from "classnames"
|
||||
|
||||
import { WithPlayerContext } from "@contexts/WithPlayerContext"
|
||||
import { Context as PlaylistContext } from "@contexts/WithPlaylistContext"
|
||||
import {
|
||||
WithPlayerContext,
|
||||
usePlayerStateContext,
|
||||
} from "@contexts/WithPlayerContext"
|
||||
|
||||
import LoadMore from "@components/LoadMore"
|
||||
import { Icons } from "@components/Icons"
|
||||
@ -24,6 +25,8 @@ const TrackList = ({
|
||||
hasMore,
|
||||
noHeader = false,
|
||||
}) => {
|
||||
const [{ track_manifest, playback_status }] = usePlayerStateContext()
|
||||
|
||||
const showListHeader = !noHeader && (tracks.length > 0 || searchResults)
|
||||
|
||||
if (!searchResults && tracks.length === 0) {
|
||||
@ -62,7 +65,7 @@ const TrackList = ({
|
||||
key={item._id}
|
||||
order={item._id} // Consider using index if order matters
|
||||
track={item}
|
||||
onPlay={() => onTrackClick(item)}
|
||||
onPlay={onTrackClick}
|
||||
changeState={(update) =>
|
||||
onTrackStateChange(item._id, update)
|
||||
}
|
||||
@ -76,19 +79,19 @@ const TrackList = ({
|
||||
onBottom={onLoadMore}
|
||||
hasMore={hasMore}
|
||||
>
|
||||
<WithPlayerContext>
|
||||
{tracks.map((item, index) => (
|
||||
<MusicTrack
|
||||
key={item._id} // Use unique ID for key
|
||||
order={index + 1}
|
||||
track={item}
|
||||
onPlay={() => onTrackClick(item)}
|
||||
changeState={(update) =>
|
||||
onTrackStateChange(item._id, update)
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</WithPlayerContext>
|
||||
{tracks.map((item, index) => (
|
||||
<MusicTrack
|
||||
key={item._id}
|
||||
order={index + 1}
|
||||
track={item}
|
||||
onPlay={onTrackClick}
|
||||
isCurrent={item._id === track_manifest?._id}
|
||||
isPlaying={
|
||||
item._id === track_manifest?._id &&
|
||||
playback_status === "playing"
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</LoadMore>
|
||||
)}
|
||||
</div>
|
||||
|
@ -2,14 +2,13 @@ import React from "react"
|
||||
import * as antd from "antd"
|
||||
import classnames from "classnames"
|
||||
|
||||
import RGBStringToValues from "@utils/rgbToValues"
|
||||
|
||||
import ImageViewer from "@components/ImageViewer"
|
||||
import { Icons } from "@components/Icons"
|
||||
|
||||
import MusicModel from "@models/music"
|
||||
import MenuItemsBase from "./menuItems"
|
||||
import MenuHandlers from "./menuHandlers"
|
||||
|
||||
import { usePlayerStateContext } from "@contexts/WithPlayerContext"
|
||||
import RGBStringToValues from "@utils/rgbToValues"
|
||||
import { Context as PlaylistContext } from "@contexts/WithPlaylistContext"
|
||||
|
||||
import "./index.less"
|
||||
@ -22,128 +21,18 @@ function secondsToIsoTime(seconds) {
|
||||
.padStart(2, "0")}`
|
||||
}
|
||||
|
||||
const handlers = {
|
||||
like: async (ctx, track) => {
|
||||
await MusicModel.toggleItemFavourite("track", track._id, true)
|
||||
|
||||
ctx.changeState({
|
||||
liked: true,
|
||||
})
|
||||
ctx.closeMenu()
|
||||
},
|
||||
unlike: async (ctx, track) => {
|
||||
await MusicModel.toggleItemFavourite("track", track._id, false)
|
||||
|
||||
ctx.changeState({
|
||||
liked: false,
|
||||
})
|
||||
ctx.closeMenu()
|
||||
},
|
||||
add_to_playlist: async (ctx, track) => {},
|
||||
add_to_queue: async (ctx, track) => {
|
||||
await app.cores.player.queue.add(track)
|
||||
},
|
||||
play_next: async (ctx, track) => {
|
||||
await app.cores.player.queue.add(track, { next: true })
|
||||
},
|
||||
}
|
||||
|
||||
const Track = (props) => {
|
||||
const [{ loading, track_manifest, playback_status }] =
|
||||
usePlayerStateContext()
|
||||
|
||||
const Track = React.memo((props) => {
|
||||
const playlist_ctx = React.useContext(PlaylistContext)
|
||||
|
||||
const [moreMenuOpened, setMoreMenuOpened] = React.useState(false)
|
||||
const [liked, setLiked] = React.useState(props.track.liked)
|
||||
|
||||
const isCurrent = track_manifest?._id === props.track._id
|
||||
const isPlaying = isCurrent && playback_status === "playing"
|
||||
const trackDuration = React.useMemo(() => {
|
||||
return props.track?.metadata?.duration ?? props.track?.duration
|
||||
}, [props.track])
|
||||
|
||||
const handleClickPlayBtn = () => {
|
||||
if (typeof props.onPlay === "function") {
|
||||
return props.onPlay(props.track)
|
||||
}
|
||||
|
||||
if (typeof props.onClickPlayBtn === "function") {
|
||||
props.onClickPlayBtn(props.track)
|
||||
}
|
||||
|
||||
if (!isCurrent) {
|
||||
app.cores.player.start(props.track)
|
||||
} else {
|
||||
app.cores.player.playback.toggle()
|
||||
}
|
||||
}
|
||||
|
||||
const handleOnClickItem = React.useCallback(() => {
|
||||
if (props.onClick) {
|
||||
props.onClick(props.track)
|
||||
}
|
||||
|
||||
if (app.isMobile) {
|
||||
handleClickPlayBtn()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const handleMoreMenuOpen = React.useCallback(() => {
|
||||
if (app.isMobile) {
|
||||
return
|
||||
}
|
||||
|
||||
return setMoreMenuOpened((prev) => {
|
||||
return !prev
|
||||
})
|
||||
}, [])
|
||||
|
||||
const handleMoreMenuItemClick = React.useCallback((e) => {
|
||||
const { key } = e
|
||||
|
||||
if (typeof handlers[key] === "function") {
|
||||
return handlers[key](
|
||||
{
|
||||
closeMenu: () => {
|
||||
setMoreMenuOpened(false)
|
||||
},
|
||||
changeState: props.changeState,
|
||||
},
|
||||
props.track,
|
||||
)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const moreMenuItems = React.useMemo(() => {
|
||||
const items = [
|
||||
{
|
||||
key: "like",
|
||||
icon: <Icons.MdFavorite />,
|
||||
label: "Like",
|
||||
},
|
||||
{
|
||||
key: "share",
|
||||
icon: <Icons.MdShare />,
|
||||
label: "Share",
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
key: "add_to_playlist",
|
||||
icon: <Icons.MdPlaylistAdd />,
|
||||
label: "Add to playlist",
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
type: "divider",
|
||||
},
|
||||
{
|
||||
key: "add_to_queue",
|
||||
icon: <Icons.MdQueueMusic />,
|
||||
label: "Add to queue",
|
||||
},
|
||||
{
|
||||
key: "play_next",
|
||||
icon: <Icons.MdSkipNext />,
|
||||
label: "Play next",
|
||||
},
|
||||
]
|
||||
const menuItems = React.useMemo(() => {
|
||||
const items = [...MenuItemsBase]
|
||||
|
||||
if (props.track.liked) {
|
||||
items[0] = {
|
||||
@ -170,22 +59,68 @@ const Track = (props) => {
|
||||
return items
|
||||
}, [props.track])
|
||||
|
||||
const trackDuration =
|
||||
props.track?.metadata?.duration ?? props.track?.duration
|
||||
const handleClickPlayBtn = React.useCallback(() => {
|
||||
if (typeof props.onPlay === "function") {
|
||||
return props.onPlay(props.track)
|
||||
}
|
||||
|
||||
if (typeof props.onClickPlayBtn === "function") {
|
||||
props.onClickPlayBtn(props.track)
|
||||
}
|
||||
|
||||
if (!props.isCurrent) {
|
||||
app.cores.player.start(props.track)
|
||||
} else {
|
||||
app.cores.player.playback.toggle()
|
||||
}
|
||||
}, [props.isCurrent])
|
||||
|
||||
const handleOnClickItem = React.useCallback(() => {
|
||||
if (props.onClick) {
|
||||
props.onClick(props.track)
|
||||
}
|
||||
|
||||
if (app.isMobile) {
|
||||
handleClickPlayBtn()
|
||||
}
|
||||
}, [props.track])
|
||||
|
||||
const handleMoreMenuOpen = React.useCallback(() => {
|
||||
if (app.isMobile) {
|
||||
return
|
||||
}
|
||||
|
||||
return setMoreMenuOpened((prev) => {
|
||||
return !prev
|
||||
})
|
||||
}, [])
|
||||
|
||||
const handleMoreMenuItemClick = React.useCallback(
|
||||
(e) => {
|
||||
const { key } = e
|
||||
|
||||
if (typeof MenuHandlers[key] === "function") {
|
||||
return MenuHandlers[key](
|
||||
{
|
||||
close: () => {
|
||||
setMoreMenuOpened(false)
|
||||
},
|
||||
setLiked: setLiked,
|
||||
},
|
||||
props.track,
|
||||
)
|
||||
}
|
||||
},
|
||||
[props.track],
|
||||
)
|
||||
|
||||
return (
|
||||
<div
|
||||
id={props.track._id}
|
||||
className={classnames("music-track", {
|
||||
["current"]: isCurrent,
|
||||
["playing"]: isPlaying,
|
||||
["loading"]: isCurrent && loading,
|
||||
["current"]: props.isCurrent,
|
||||
["playing"]: props.isPlaying,
|
||||
})}
|
||||
style={{
|
||||
"--cover_average-color": RGBStringToValues(
|
||||
track_manifest?.cover_analysis?.rgb,
|
||||
),
|
||||
}}
|
||||
>
|
||||
<div className="music-track_background" />
|
||||
|
||||
@ -204,7 +139,7 @@ const Track = (props) => {
|
||||
type="primary"
|
||||
shape="circle"
|
||||
icon={
|
||||
isPlaying ? (
|
||||
props.isPlaying ? (
|
||||
<Icons.MdPause />
|
||||
) : (
|
||||
<Icons.MdPlayArrow />
|
||||
@ -212,14 +147,6 @@ const Track = (props) => {
|
||||
}
|
||||
onClick={handleClickPlayBtn}
|
||||
/>
|
||||
|
||||
{/* {props.track?.metadata?.duration && (
|
||||
<div className="music-track_play_duration">
|
||||
{secondsToIsoTime(
|
||||
props.track.metadata.duration,
|
||||
)}
|
||||
</div>
|
||||
)} */}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -267,7 +194,7 @@ const Track = (props) => {
|
||||
|
||||
<antd.Dropdown
|
||||
menu={{
|
||||
items: moreMenuItems,
|
||||
items: menuItems,
|
||||
onClick: handleMoreMenuItemClick,
|
||||
}}
|
||||
onOpenChange={handleMoreMenuOpen}
|
||||
@ -281,6 +208,8 @@ const Track = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
Track.displayName = "Track"
|
||||
|
||||
export default Track
|
||||
|
31
packages/app/src/components/Music/Track/menuHandlers.js
Normal file
31
packages/app/src/components/Music/Track/menuHandlers.js
Normal file
@ -0,0 +1,31 @@
|
||||
import MusicModel from "@models/music"
|
||||
|
||||
export default {
|
||||
like: async (ctx, track) => {
|
||||
await MusicModel.toggleItemFavourite("track", track._id, true)
|
||||
|
||||
ctx.changeState({
|
||||
liked: true,
|
||||
})
|
||||
ctx.close()
|
||||
},
|
||||
unlike: async (ctx, track) => {
|
||||
await MusicModel.toggleItemFavourite("track", track._id, false)
|
||||
|
||||
ctx.changeState({
|
||||
liked: false,
|
||||
})
|
||||
ctx.close()
|
||||
},
|
||||
add_to_playlist: async (ctx, track) => {},
|
||||
add_to_queue: async (ctx, track) => {
|
||||
await app.cores.player.queue.add(track)
|
||||
},
|
||||
play_next: async (ctx, track) => {
|
||||
await app.cores.player.queue.add(track, { next: true })
|
||||
},
|
||||
copy_id: (ctx, track) => {
|
||||
console.log("copy_id", track)
|
||||
navigator.clipboard.writeText(track._id)
|
||||
},
|
||||
}
|
42
packages/app/src/components/Music/Track/menuItems.jsx
Normal file
42
packages/app/src/components/Music/Track/menuItems.jsx
Normal file
@ -0,0 +1,42 @@
|
||||
import { Icons } from "@components/Icons"
|
||||
|
||||
export default [
|
||||
{
|
||||
key: "like",
|
||||
icon: <Icons.MdFavorite />,
|
||||
label: "Like",
|
||||
},
|
||||
{
|
||||
key: "share",
|
||||
icon: <Icons.MdShare />,
|
||||
label: "Share",
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
key: "add_to_playlist",
|
||||
icon: <Icons.MdPlaylistAdd />,
|
||||
label: "Add to playlist",
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
type: "divider",
|
||||
},
|
||||
{
|
||||
key: "add_to_queue",
|
||||
icon: <Icons.MdQueueMusic />,
|
||||
label: "Add to queue",
|
||||
},
|
||||
{
|
||||
key: "play_next",
|
||||
icon: <Icons.MdSkipNext />,
|
||||
label: "Play next",
|
||||
},
|
||||
{
|
||||
type: "divider",
|
||||
},
|
||||
{
|
||||
key: "copy_id",
|
||||
icon: <Icons.MdLink />,
|
||||
label: "Copy ID",
|
||||
},
|
||||
]
|
Loading…
x
Reference in New Issue
Block a user