mirror of
https://github.com/captbaritone/webamp.git
synced 2026-08-01 22:45:18 +00:00
Reverse, randomize, sort
This commit is contained in:
parent
ee37da98b2
commit
308a1bcd3f
6 changed files with 113 additions and 14 deletions
|
|
@ -4,7 +4,13 @@ import skinParser from "./skinParser";
|
|||
import { BANDS } from "./constants";
|
||||
import { getEqfData } from "./selectors";
|
||||
|
||||
import { clamp, base64FromArrayBuffer, downloadURI, normalize } from "./utils";
|
||||
import {
|
||||
clamp,
|
||||
base64FromArrayBuffer,
|
||||
downloadURI,
|
||||
normalize,
|
||||
sort
|
||||
} from "./utils";
|
||||
import {
|
||||
CLOSE_WINAMP,
|
||||
LOAD_AUDIO_FILE,
|
||||
|
|
@ -25,7 +31,10 @@ import {
|
|||
CLOSE_EQUALIZER_WINDOW,
|
||||
REMOVE_TRACKS,
|
||||
PLAY,
|
||||
PAUSE
|
||||
PAUSE,
|
||||
REVERSE_LIST,
|
||||
RANDOMIZE_LIST,
|
||||
SET_TRACK_ORDER
|
||||
} from "./actionTypes";
|
||||
|
||||
export function play() {
|
||||
|
|
@ -247,3 +256,21 @@ export function removeSelectedTracks() {
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function reverseList() {
|
||||
return { type: REVERSE_LIST };
|
||||
}
|
||||
|
||||
export function randomizeList() {
|
||||
return { type: RANDOMIZE_LIST };
|
||||
}
|
||||
|
||||
export function sortListByTitle() {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const trackOrder = sort(state.playlist.trackOrder, i =>
|
||||
state.tracks[i].title.toLowerCase()
|
||||
);
|
||||
return dispatch({ type: SET_TRACK_ORDER, trackOrder });
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,3 +52,6 @@ export const CROP_TRACKS = "CROP_TRACKS";
|
|||
export const FILE_INFO = "FILE_INFO";
|
||||
export const REMOVE_TRACKS = "REMOVE_TRACKS";
|
||||
export const SET_AVALIABLE_SKINS = "SET_AVALIABLE_SKINS";
|
||||
export const REVERSE_LIST = "REVERSE_LIST";
|
||||
export const RANDOMIZE_LIST = "RANDOMIZE_LIST";
|
||||
export const SET_TRACK_ORDER = "SET_TRACK_ORDER";
|
||||
|
|
|
|||
|
|
@ -1,17 +1,35 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { FILE_INFO } from "../../actionTypes";
|
||||
import {
|
||||
reverseList,
|
||||
randomizeList,
|
||||
sortListByTitle
|
||||
} from "../../actionCreators";
|
||||
import PlaylistMenu from "./PlaylistMenu";
|
||||
import { ContextMenu, Hr, Node } from "../ContextMenu";
|
||||
|
||||
/* eslint-disable no-alert */
|
||||
/* TODO: This should really be kitty-corner to the upper right hand corner of the MiscMenu */
|
||||
const SortContextMenu = props => (
|
||||
<ContextMenu style={{ width: "100%", height: "100%" }} top handle={<div />}>
|
||||
<Node label="Sort list by title" onClick={props.sortListByTitle} />
|
||||
<Hr />
|
||||
<Node label="Reverse list" onClick={props.reverseList} />
|
||||
<Node label="Randomize list" onClick={props.randomizeList} />
|
||||
</ContextMenu>
|
||||
);
|
||||
|
||||
const ConnectedSortcontextMenu = connect(null, {
|
||||
reverseList,
|
||||
randomizeList,
|
||||
sortListByTitle
|
||||
})(SortContextMenu);
|
||||
|
||||
const MiscMenu = () => (
|
||||
<PlaylistMenu id="playlist-misc-menu">
|
||||
<div
|
||||
className="sort-list"
|
||||
onClick={() => alert("Not supported in Winamp2-js")}
|
||||
/>
|
||||
{/* onClick={props.fileInfo} */}
|
||||
<div className="sort-list" onClick={e => e.stopPropagation()}>
|
||||
<ConnectedSortcontextMenu />
|
||||
</div>
|
||||
<div
|
||||
className="file-info"
|
||||
onClick={() => alert("Not supported in Winamp2-js")}
|
||||
|
|
@ -23,7 +41,4 @@ const MiscMenu = () => (
|
|||
</PlaylistMenu>
|
||||
);
|
||||
|
||||
const mapDispatchToProps = {
|
||||
fileInfo: () => ({ type: FILE_INFO })
|
||||
};
|
||||
export default connect(null, mapDispatchToProps)(MiscMenu);
|
||||
export default MiscMenu;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ import {
|
|||
toggleShuffle,
|
||||
openFileDialog,
|
||||
seekForward,
|
||||
seekBackward
|
||||
seekBackward,
|
||||
reverseList
|
||||
} from "./actionCreators";
|
||||
|
||||
import {
|
||||
|
|
@ -40,6 +41,9 @@ export default function(fileInput, { dispatch }) {
|
|||
break;
|
||||
case 76: // CTRL+L FIXME
|
||||
break;
|
||||
case 82: // CTRL+R
|
||||
dispatch(reverseList());
|
||||
break;
|
||||
case 84: // CTRL+T
|
||||
dispatch({ type: TOGGLE_TIME_MODE });
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -45,9 +45,13 @@ import {
|
|||
REMOVE_TRACKS,
|
||||
SET_AVALIABLE_SKINS,
|
||||
LOAD_AUDIO_FILE,
|
||||
LOAD_AUDIO_URL
|
||||
LOAD_AUDIO_URL,
|
||||
REVERSE_LIST,
|
||||
RANDOMIZE_LIST,
|
||||
SET_TRACK_ORDER
|
||||
} from "./actionTypes";
|
||||
import { playlistEnabled } from "./config";
|
||||
import { shuffle } from "./utils";
|
||||
|
||||
const mapObject = (obj, iteratee) =>
|
||||
// TODO: Could return the original reference if no values change
|
||||
|
|
@ -317,6 +321,20 @@ const playlist = (state = defaultPlaylistState, action) => {
|
|||
...state,
|
||||
trackOrder: state.trackOrder.filter(id => !action.ids.includes(id))
|
||||
};
|
||||
case REVERSE_LIST:
|
||||
return {
|
||||
...state,
|
||||
trackOrder: [...state.trackOrder].reverse()
|
||||
};
|
||||
case RANDOMIZE_LIST:
|
||||
return {
|
||||
...state,
|
||||
trackOrder: shuffle(state.trackOrder)
|
||||
};
|
||||
case SET_TRACK_ORDER:
|
||||
const { trackOrder } = action;
|
||||
return { ...state, trackOrder };
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
|||
32
js/utils.js
32
js/utils.js
|
|
@ -114,3 +114,35 @@ export const segment = (min, max, value, newValues) => {
|
|||
|
||||
export const arraysAreEqual = (a, b) =>
|
||||
a.length === b.length && a.every((value, i) => value === b[i]);
|
||||
|
||||
// https://bost.ocks.org/mike/shuffle/
|
||||
// Shuffle an array in O(n)
|
||||
export const shuffle = array => {
|
||||
const sorted = [...array];
|
||||
let m = sorted.length;
|
||||
|
||||
// While there remain elements to shuffle…
|
||||
while (m) {
|
||||
// Pick a remaining element…
|
||||
const i = Math.floor(Math.random() * m--);
|
||||
|
||||
// And swap it with the current element.
|
||||
const val = sorted[m];
|
||||
sorted[m] = sorted[i];
|
||||
sorted[i] = val;
|
||||
}
|
||||
|
||||
return sorted;
|
||||
};
|
||||
|
||||
export const sort = (array, iteratee) =>
|
||||
array.sort((a, b) => {
|
||||
const aKey = iteratee(a);
|
||||
const bKey = iteratee(b);
|
||||
if (aKey < bKey) {
|
||||
return -1;
|
||||
} else if (aKey > bKey) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue