Skip to content

Commit

Permalink
feat: react-drag-listview => sortablejs for support audio list sort o…
Browse files Browse the repository at this point in the history
…n mobile #223
  • Loading branch information
lijinke666 committed Feb 7, 2021
1 parent 0cab12e commit e173a26
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 90 deletions.
6 changes: 3 additions & 3 deletions CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ ReactDOM.render(
> 中文版本文档可能不完整, 请以英文版为准, 维护两个版本太累了
| 属性 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| --- | --- | --- | --- | --- | --- | --- |
| className | `string` | `-` | 附加的 className |
| audioLists | `object[]` | `-` | 播放列表 : {name: "YOUR_AUDIO_NAME",singer: "YOUR_AUDIO_SINGER_NAME",cover: "YOUR_AUDIO_COVER",musicSrc: "YOUR_AUDIO_SRC"} |
| theme | `string` | `dark` | 播放器主题 可选 'light'(白天) 和 'dark'(黑夜) 两种 |
Expand Down Expand Up @@ -152,7 +152,7 @@ ReactDOM.render(
| onAudioListsPanelChange | `function(panelVisible)` | `-` | 播放列表打开或关闭的 钩子函数 |
| onThemeChange | `function(theme)` | `-` | 主题切换后的 钩子函数 |
| onModeChange | `function(mode)` | `-` | 模式切换发生改变时的 钩子函数 |
| onAudioListsDragEnd | `function(fromIndex,toIndex)` | `-` | 列表歌曲拖拽后 钩子函数 |
| onAudioListsSortEnd | `function(fromIndex,toIndex)` | `-` | 列表歌曲拖拽后 钩子函数 |
| onAudioLyricChange | `function(lineNum, currentLyric)` | `-` | 当前播放的歌词改变回调 |
| getContainer | `() => HTMLElement` \| `Selectors` | `document.body` | 播放器挂载的节点 默认在 body |
| getAudioInstance | `(instance: HTMLAudioElement) => void` | `-` | 获取原始的 audio 实例, 可以用它所有的 api 做你想做的事情 |
Expand Down Expand Up @@ -396,7 +396,7 @@ export interface ReactJkMusicPlayerProps {
onModeChange?: (mode: ReactJkMusicPlayerMode) => void
onAudioListsPanelChange?: (panelVisible: boolean) => void
onAudioPlayTrackChange?: (fromIndex: number, endIndex: number) => void
onAudioListsDragEnd?: (
onAudioListsSortEnd?: (
currentPlayId: string,
audioLists: Array<ReactJkMusicPlayerAudioList>,
audioInfo: ReactJkMusicPlayerAudioInfo,
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ npm install react-jinke-music-player --save
- [x] Support theme switch
- [x] Support typescript (d.ts)
- [x] Support lyric
- [x] Support audio list sortable
- [x] Play list
- [x] Full player features
- [x] [Server-Side Rendering](#bulb-server-side-rendering)
Expand Down Expand Up @@ -182,7 +183,7 @@ ReactDOM.render(
| onAudioListsPanelChange | `function(panelVisible)` | `-` | audio lists panel change handle |
| onThemeChange | `function(theme)` | `-` | theme change handle |
| onModeChange | `function(mode)` | `-` | mode change handle |
| onAudioListsDragEnd | `function(fromIndex,endIndex)` | `-` | audio lists drag end handle |
| onAudioListsSortEnd | `function(oldIndex,newIndex)` | `-` | audio lists sort end handle, use [SortableJS](https://github.com/SortableJS/Sortable) |
| onAudioLyricChange | `function(lineNum, currentLyric)` | `-` | audio lyric change handle |
| getContainer | `() => HTMLElement` \| `Selectors` | `document.body` | Return the mount node for Music player |
| getAudioInstance | `(instance: HTMLAudioElement) => void` | `-` | get origin audio element instance , you can use it do everything |
Expand All @@ -201,6 +202,7 @@ ReactDOM.render(
| renderAudioTitle | `(audioInfo, isMobile) => ReactNode` | `-` | use `locale.audioTitle` to set `audio` tag title, the api can render custom jsx element for display |
| mobileMediaQuery | `string` | `(max-width: 768px) and (orientation : portrait)` | custom mobile media query string, eg use the mobile version UI on iPad. <https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries> |
| volumeFade | `{ fadeIn: number(ms), fadeOut: number(ms) }` | `-` | audio fade in and out. [Detail](#bulb-audio-volume-fade-in-and-fade-out) |
| sortableOptions | `{ fadeIn: number(ms), fadeOut: number(ms) }` | `{swap: true, animation: 100, swapClass: 'audio-lists-panel-sortable-highlight-bg'}` | [SortableJs Options](https://github.com/SortableJS/Sortable#options) |

## :bulb: Custom operation ui

Expand Down
4 changes: 2 additions & 2 deletions example/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,8 @@ const options = {
console.log('audio lists panel visible:', panelVisible)
},

onAudioListsDragEnd(fromIndex, endIndex) {
console.log('audio lists drag end:', fromIndex, endIndex)
onAudioListsSortEnd(oldIndex, newIndex) {
console.log('audio lists sort end:', oldIndex, newIndex)
},

onAudioLyricChange(lineNum, currentLyric) {
Expand Down
7 changes: 2 additions & 5 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,7 @@ export interface ReactJkMusicPlayerProps {
audioLists: Array<ReactJkMusicPlayerAudioListProps>,
audioInfo: ReactJkMusicPlayerAudioInfo,
) => void
onAudioListsDragEnd?: (
currentPlayId: string,
audioLists: Array<ReactJkMusicPlayerAudioListProps>,
audioInfo: ReactJkMusicPlayerAudioInfo,
) => void
onAudioListsSortEnd?: (oldIndex: number, newIndex: number) => void
showDownload?: boolean
showPlay?: boolean
showReload?: boolean
Expand Down Expand Up @@ -238,6 +234,7 @@ export interface ReactJkMusicPlayerProps {
fadeIn?: number
fadeOut?: number
}
sortableOptions?: object
}

export default class ReactJkMusicPlayer extends React.PureComponent<
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@
"prop-types": "^15.7.2",
"rc-slider": "^9.7.1",
"rc-switch": "^3.2.2",
"react-drag-listview": "^0.1.8",
"react-draggable": "^4.4.3"
"react-draggable": "^4.4.3",
"sortablejs": "^1.13.0"
},
"bundlesize": [
{
Expand All @@ -126,6 +126,7 @@
"@semantic-release/changelog": "^5.0.1",
"@semantic-release/git": "^9.0.0",
"@types/jest": "^26.0.20",
"@types/sortablejs": "^1.10.6",
"all-contributors-cli": "^6.19.0",
"autoprefixer": "^10.2.4",
"babel-core": "^7.0.0-bridge.0",
Expand Down
108 changes: 50 additions & 58 deletions src/components/AudioListsPanel.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import cls from 'classnames'
import React, { memo } from 'react'
import ReactDragListView from 'react-drag-listview/lib/ReactDragListView'
import SORTABLE_CONFIG from '../config/sortable'

const AudioListsPanel = ({
audioLists,
Expand All @@ -13,7 +13,6 @@ const AudioListsPanel = ({
glassBg,
remove,
removeId,
audioListsDragEnd,
isMobile,
locale,
icon,
Expand Down Expand Up @@ -60,65 +59,58 @@ const AudioListsPanel = ({
})}
>
{audioLists.length >= 1 ? (
<ReactDragListView
nodeSelector="li"
handleSelector=".player-name"
lineClassName="audio-lists-panel-drag-line"
onDragEnd={audioListsDragEnd}
>
<ul>
{audioLists.map((audio) => {
const { name, singer } = audio
const isCurrentPlaying = playId === audio.id
return (
<li
key={audio.id}
title={
!playing
? locale.clickToPlayText
<ul className={SORTABLE_CONFIG.selector}>
{audioLists.map((audio) => {
const { name, singer } = audio
const isCurrentPlaying = playId === audio.id
return (
<li
key={audio.id}
title={
!playing
? locale.clickToPlayText
: isCurrentPlaying
? locale.clickToPauseText
: locale.clickToPlayText
}
className={cls(
'audio-item',
{ playing: isCurrentPlaying },
{ pause: !playing },
{ remove: removeId === audio.id },
)}
onClick={() => onPlay(audio.id)}
>
<span className="group player-status">
<span className="player-icons">
{isCurrentPlaying && loading
? icon.loading
: isCurrentPlaying
? locale.clickToPauseText
: locale.clickToPlayText
}
className={cls(
'audio-item',
{ playing: isCurrentPlaying },
{ pause: !playing },
{ remove: removeId === audio.id },
)}
onClick={() => onPlay(audio.id)}
>
<span className="group player-status">
<span className="player-icons">
{isCurrentPlaying && loading
? icon.loading
: isCurrentPlaying
? playing
? icon.pause
: icon.play
: undefined}
</span>
</span>
<span className="group player-name" title={name}>
{name}
? playing
? icon.pause
: icon.play
: undefined}
</span>
<span className="group player-singer" title={singer}>
{singer}
</span>
<span className="group player-name" title={name}>
{name}
</span>
<span className="group player-singer" title={singer}>
{singer}
</span>
{remove && (
<span
className="group player-delete"
title={locale.clickToDeleteText(name)}
onClick={onDelete(audio.id)}
>
{icon.close}
</span>
{remove && (
<span
className="group player-delete"
title={locale.clickToDeleteText(name)}
onClick={onDelete(audio.id)}
>
{icon.close}
</span>
)}
</li>
)
})}
</ul>
</ReactDragListView>
)}
</li>
)
})}
</ul>
) : (
<>
<span>{icon.empty}</span>
Expand Down
3 changes: 2 additions & 1 deletion src/config/propTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export default {
onModeChange: PropTypes.func,
onAudioListsPanelChange: PropTypes.func,
onAudioPlayTrackChange: PropTypes.func,
onAudioListsDragEnd: PropTypes.func,
onAudioListsSortEnd: PropTypes.func,
onAudioLyricChange: PropTypes.func,
showDownload: PropTypes.bool,
showPlay: PropTypes.bool,
Expand Down Expand Up @@ -119,4 +119,5 @@ export default {
fadeIn: PropTypes.number,
fadeOut: PropTypes.number,
}),
sortableOptions: PropTypes.object,
}
6 changes: 6 additions & 0 deletions src/config/sortable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
selector: 'audio-lists-panel-content-wrap',
swapClass: 'audio-lists-panel-sortable-highlight-bg',
swap: true,
animation: 100,
}
44 changes: 37 additions & 7 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Switch from 'rc-switch'
import React, { cloneElement, createRef, PureComponent } from 'react'
import { createPortal } from 'react-dom'
import Draggable from 'react-draggable'
import Sortable, { Swap } from 'sortablejs'
import AudioListsPanel from './components/AudioListsPanel'
import CircleProcessBar from './components/CircleProcessBar'
import {
Expand Down Expand Up @@ -58,6 +59,7 @@ import {
DEFAULT_VOLUME,
DEFAULT_REMOVE_ID,
} from './config/player'
import SORTABLE_CONFIG from './config/sortable'
import LOCALE_CONFIG from './locale'
import Lyric from './lyric'
import {
Expand Down Expand Up @@ -188,6 +190,8 @@ export default class ReactJkMusicPlayer extends PureComponent {
fadeIn: 0,
fadeOut: 0,
},
// https://github.com/SortableJS/Sortable#options
sortableOptions: {},
}

static propTypes = PROP_TYPES
Expand Down Expand Up @@ -674,7 +678,6 @@ export default class ReactJkMusicPlayer extends PureComponent {
remove={remove}
onDelete={this.onDeleteAudioLists}
removeId={removeId}
audioListsDragEnd={this.onAudioListsDragEnd}
locale={locale}
/>
{/* 播放模式提示框 */}
Expand Down Expand Up @@ -1629,26 +1632,39 @@ export default class ReactJkMusicPlayer extends PureComponent {
this.setState({ theme })
}

onAudioListsDragEnd = (fromIndex, toIndex) => {
onAudioListsSortEnd = ({ oldIndex, newIndex }) => {
if (oldIndex === newIndex) {
return
}

const { playId, audioLists } = this.state
const _audioLists = [...audioLists]
const item = _audioLists.splice(fromIndex, 1)[0]
_audioLists.splice(toIndex, 0, item)
const item = _audioLists.splice(oldIndex, 1)[0]
_audioLists.splice(newIndex, 0, item)

// 如果拖动正在播放的歌曲 播放Id 等于 拖动后的index
const _playId = fromIndex === playId ? toIndex : playId
const _playId = oldIndex === playId ? newIndex : playId

this.setState({ audioLists: _audioLists, playId: _playId })

this.props.onAudioListsDragEnd &&
this.props.onAudioListsDragEnd(fromIndex, toIndex)
this.props.onAudioListsSortEnd &&
this.props.onAudioListsSortEnd(oldIndex, newIndex)

this.props.onAudioListsChange &&
this.props.onAudioListsChange(
_playId,
_audioLists,
this.getBaseAudioInfo(),
)

// TODO: remove
if (this.props.onAudioListsDragEnd) {
// eslint-disable-next-line no-console
console.warn(
'[Deprecated] onAudioListsDragEnd is deprecated. please use onAudioListsSortEnd(oldIndex, newIndex){}',
)
this.props.onAudioListsDragEnd(oldIndex, newIndex)
}
}

saveLastPlayStatus = () => {
Expand Down Expand Up @@ -2313,6 +2329,7 @@ export default class ReactJkMusicPlayer extends PureComponent {
this.removeMobileListener()
this.removeLyric()
this._onDestroyed()
this.sortable && this.sortable.destroy()
}

onAudioCanPlay = () => {
Expand All @@ -2324,6 +2341,18 @@ export default class ReactJkMusicPlayer extends PureComponent {
})
}

initSortableAudioLists = () => {
Sortable.mount(new Swap())

const { sortableOptions } = this.props
const { selector, ...defaultOptions } = SORTABLE_CONFIG
this.sortable = new Sortable(document.querySelector(`.${selector}`), {
onEnd: this.onAudioListsSortEnd,
...defaultOptions,
...sortableOptions,
})
}

// eslint-disable-next-line camelcase
UNSAFE_componentWillReceiveProps(nextProps) {
const {
Expand Down Expand Up @@ -2391,5 +2420,6 @@ export default class ReactJkMusicPlayer extends PureComponent {
this.addSystemThemeListener()
this.initPlayer()
this.onGetAudioInstance()
this.initSortableAudioLists()
}
}
5 changes: 3 additions & 2 deletions src/styles/audioListsPanel.less
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
@import './vars.less';
@import './mixins.less';

.audio-lists-panel-drag-line {
border: 1px solid @primary-color !important;
.audio-lists-panel-sortable-highlight-bg {
background-color: @lists-sortable-highlight-bg !important;
}

.audio-lists-panel {
overflow: hidden;
position: fixed;
Expand Down
1 change: 1 addition & 0 deletions src/styles/vars.less
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
@controller-bg-light: @primary-color-light;
@panel-bg-dark: @primary-color-dark;
@controller-bg-dark: darken(@primary-color-light, 10%);
@lists-sortable-highlight-bg: fade(@primary-color, 15%);

@border-radius: 4px;
@music-player-panel-height: 80px;
Expand Down
Loading

0 comments on commit e173a26

Please sign in to comment.