1
0
mirror of https://github.com/ragestudio/comty.git synced 2025-07-11 10:14:16 +00:00

use swappy

This commit is contained in:
SrGooglo 2025-02-11 16:15:16 +00:00
parent 7ae3c19e7d
commit bca40318bd
2 changed files with 354 additions and 338 deletions
packages/app/src/components/MusicStudio/ReleaseEditor/tabs/Tracks
components/TrackListItem
index.jsx

@ -25,7 +25,7 @@ const TrackListItem = (props) => {
content: <TrackEditor />, content: <TrackEditor />,
props: { props: {
track: track, track: track,
} },
}) })
} }
@ -33,24 +33,19 @@ const TrackListItem = (props) => {
props.onDelete(track.uid) props.onDelete(track.uid)
} }
return <Draggable console.log("render")
key={track._id ?? track.id}
draggableId={track.id ?? track._id} return (
index={props.index} <div
>
{
(provided, snapshot) => {
return <div
className={classnames( className={classnames(
"music-studio-release-editor-tracks-list-item", "music-studio-release-editor-tracks-list-item",
{ {
["loading"]: loading, ["loading"]: loading,
["failed"]: !!error, ["failed"]: !!error,
["disabled"]: props.disabled, ["disabled"]: props.disabled,
} },
)} )}
ref={provided.innerRef} data-swapy-item={track.id ?? track._id}
{...provided.draggableProps}
> >
<div <div
className="music-studio-release-editor-tracks-list-item-progress" className="music-studio-release-editor-tracks-list-item-progress"
@ -63,9 +58,7 @@ const TrackListItem = (props) => {
<span>{props.index + 1}</span> <span>{props.index + 1}</span>
</div> </div>
{ {props.uploading.working && <Icons.LoadingOutlined />}
props.uploading.working && <Icons.LoadingOutlined />
}
<Image <Image
src={track.cover} src={track.cover}
@ -99,16 +92,14 @@ const TrackListItem = (props) => {
/> />
<div <div
{...provided.dragHandleProps} data-swapy-handle
className="music-studio-release-editor-tracks-list-item-dragger" className="music-studio-release-editor-tracks-list-item-dragger"
> >
<Icons.MdDragIndicator /> <Icons.MdDragIndicator />
</div> </div>
</div> </div>
</div> </div>
} )
}
</Draggable>
} }
export default TrackListItem export default TrackListItem

@ -2,6 +2,7 @@ import React from "react"
import * as antd from "antd" import * as antd from "antd"
import classnames from "classnames" import classnames from "classnames"
import { DragDropContext, Droppable } from "react-beautiful-dnd" import { DragDropContext, Droppable } from "react-beautiful-dnd"
import { createSwapy } from "swapy"
import TrackManifest from "@cores/player/classes/TrackManifest" import TrackManifest from "@cores/player/classes/TrackManifest"
@ -13,6 +14,8 @@ import UploadHint from "./components/UploadHint"
import "./index.less" import "./index.less"
class TracksManager extends React.Component { class TracksManager extends React.Component {
swapyRef = React.createRef()
state = { state = {
list: Array.isArray(this.props.list) ? this.props.list : [], list: Array.isArray(this.props.list) ? this.props.list : [],
pendingUploads: [], pendingUploads: [],
@ -26,6 +29,27 @@ class TracksManager extends React.Component {
} }
} }
componentDidMount() {
this.swapyRef.current = createSwapy(
document.getElementById("editor-tracks-list"),
{
animation: "dynamic",
dragAxis: "y",
},
)
this.swapyRef.current.onSwapEnd((event) => {
console.log("end", event)
this.orderTrackList(
event.slotItemMap.asArray.map((item) => item.item),
)
})
}
componentWillUnmount() {
this.swapyRef.current.destroy()
}
findTrackByUid = (uid) => { findTrackByUid = (uid) => {
if (!uid) { if (!uid) {
return false return false
@ -54,7 +78,6 @@ class TracksManager extends React.Component {
this.setState({ this.setState({
list: this.state.list.filter((item) => item.uid !== uid), list: this.state.list.filter((item) => item.uid !== uid),
}) })
} }
modifyTrackByUid = (uid, track) => { modifyTrackByUid = (uid, track) => {
@ -82,7 +105,9 @@ class TracksManager extends React.Component {
return false return false
} }
const pendingUpload = this.state.pendingUploads.find((item) => item.uid === uid) const pendingUpload = this.state.pendingUploads.find(
(item) => item.uid === uid,
)
if (!pendingUpload) { if (!pendingUpload) {
this.setState({ this.setState({
@ -90,8 +115,8 @@ class TracksManager extends React.Component {
...this.state.pendingUploads, ...this.state.pendingUploads,
{ {
uid: uid, uid: uid,
progress: 0 progress: 0,
} },
], ],
}) })
} }
@ -103,12 +128,16 @@ class TracksManager extends React.Component {
} }
this.setState({ this.setState({
pendingUploads: this.state.pendingUploads.filter((item) => item.uid !== uid), pendingUploads: this.state.pendingUploads.filter(
(item) => item.uid !== uid,
),
}) })
} }
getUploadProgress = (uid) => { getUploadProgress = (uid) => {
const uploadProgressIndex = this.state.pendingUploads.findIndex((item) => item.uid === uid) const uploadProgressIndex = this.state.pendingUploads.findIndex(
(item) => item.uid === uid,
)
if (uploadProgressIndex === -1) { if (uploadProgressIndex === -1) {
return 0 return 0
@ -118,7 +147,9 @@ class TracksManager extends React.Component {
} }
updateUploadProgress = (uid, progress) => { updateUploadProgress = (uid, progress) => {
const uploadProgressIndex = this.state.pendingUploads.findIndex((item) => item.uid === uid) const uploadProgressIndex = this.state.pendingUploads.findIndex(
(item) => item.uid === uid,
)
if (uploadProgressIndex === -1) { if (uploadProgressIndex === -1) {
return false return false
@ -147,7 +178,7 @@ class TracksManager extends React.Component {
const trackManifest = new TrackManifest({ const trackManifest = new TrackManifest({
uid: uid, uid: uid,
file: change.file, file: change.file,
onChange: this.modifyTrackByUid onChange: this.modifyTrackByUid,
}) })
this.addTrackToList(trackManifest) this.addTrackToList(trackManifest)
@ -158,7 +189,9 @@ class TracksManager extends React.Component {
// remove pending file // remove pending file
this.removeTrackUIDFromPendingUploads(uid) this.removeTrackUIDFromPendingUploads(uid)
let trackManifest = this.state.list.find((item) => item.uid === uid) let trackManifest = this.state.list.find(
(item) => item.uid === uid,
)
if (!trackManifest) { if (!trackManifest) {
console.error(`Track with uid [${uid}] not found!`) console.error(`Track with uid [${uid}] not found!`)
@ -195,13 +228,15 @@ class TracksManager extends React.Component {
} }
uploadToStorage = async (req) => { uploadToStorage = async (req) => {
const response = await app.cores.remoteStorage.uploadFile(req.file, { const response = await app.cores.remoteStorage
.uploadFile(req.file, {
onProgress: this.handleTrackFileUploadProgress, onProgress: this.handleTrackFileUploadProgress,
service: "b2", service: "b2",
headers: { headers: {
transmux: "a-dash" transmux: "a-dash",
} },
}).catch((error) => { })
.catch((error) => {
console.error(error) console.error(error)
antd.message.error(error) antd.message.error(error)
@ -219,20 +254,15 @@ class TracksManager extends React.Component {
this.updateUploadProgress(file.uid, progress) this.updateUploadProgress(file.uid, progress)
} }
orderTrackList = (result) => { orderTrackList = (orderedIdsArray) => {
if (!result.destination) {
return
}
this.setState((prev) => { this.setState((prev) => {
const trackList = [...prev.list] // move all list items by id
const orderedIds = orderedIdsArray.map((id) =>
const [removed] = trackList.splice(result.source.index, 1) this.state.list.find((item) => item._id === id),
)
trackList.splice(result.destination.index, 0, removed) console.log("orderedIds", orderedIds)
return { return {
list: trackList list: orderedIds,
} }
}) })
} }
@ -240,7 +270,8 @@ class TracksManager extends React.Component {
render() { render() {
console.log(`Tracks List >`, this.state.list) console.log(`Tracks List >`, this.state.list)
return <div className="music-studio-release-editor-tracks"> return (
<div className="music-studio-release-editor-tracks">
<antd.Upload <antd.Upload
className="music-studio-tracks-uploader" className="music-studio-tracks-uploader"
onChange={this.handleUploaderStateChange} onChange={this.handleUploaderStateChange}
@ -249,65 +280,58 @@ class TracksManager extends React.Component {
accept="audio/*" accept="audio/*"
multiple multiple
> >
{ {this.state.list.length === 0 ? (
this.state.list.length === 0 ? <UploadHint />
<UploadHint /> : <antd.Button ) : (
<antd.Button
className="uploadMoreButton" className="uploadMoreButton"
icon={<Icons.FiPlus />} icon={<Icons.FiPlus />}
> >
Add another Add another
</antd.Button> </antd.Button>
} )}
</antd.Upload> </antd.Upload>
<DragDropContext
onDragEnd={this.orderTrackList}
>
<Droppable
droppableId="droppable"
>
{(provided, snapshot) => (
<div <div
{...provided.droppableProps} id="editor-tracks-list"
ref={provided.innerRef}
className="music-studio-release-editor-tracks-list" className="music-studio-release-editor-tracks-list"
> >
{ {this.state.list.length === 0 && (
this.state.list.length === 0 && <antd.Result <antd.Result status="info" title="No tracks" />
status="info" )}
title="No tracks"
/> {this.state.list.map((track, index) => {
}
{
this.state.list.map((track, index) => {
const progress = this.getUploadProgress(track.uid) const progress = this.getUploadProgress(track.uid)
return <TrackListItem return (
<div data-swapy-slot={track._id ?? track.uid}>
<TrackListItem
index={index} index={index}
track={track} track={track}
onEdit={this.modifyTrackByUid} onEdit={this.modifyTrackByUid}
onDelete={this.removeTrackByUid} onDelete={this.removeTrackByUid}
uploading={{ uploading={{
progress: progress, progress: progress,
working: this.state.pendingUploads.find((item) => item.uid === track.uid) working: this.state.pendingUploads.find(
(item) => item.uid === track.uid,
),
}} }}
disabled={progress > 0} disabled={progress > 0}
/> />
})
}
{provided.placeholder}
</div> </div>
)} )
</Droppable> })}
</DragDropContext>
</div> </div>
</div>
)
} }
} }
const ReleaseTracks = (props) => { const ReleaseTracks = (props) => {
const { state, setState } = props const { state, setState } = props
return <div className="music-studio-release-editor-tab"> return (
<div className="music-studio-release-editor-tab">
<h1>Tracks</h1> <h1>Tracks</h1>
<TracksManager <TracksManager
@ -316,11 +340,12 @@ const ReleaseTracks = (props) => {
onChangeState={(managerState) => { onChangeState={(managerState) => {
setState({ setState({
...state, ...state,
...managerState ...managerState,
}) })
}} }}
/> />
</div> </div>
)
} }
export default ReleaseTracks export default ReleaseTracks