webamp/js/actionCreators/playlist.js
2018-05-28 15:56:18 -07:00

149 lines
3.6 KiB
JavaScript

import { TRACK_HEIGHT } from "../constants";
import {
getScrollOffset,
getOverflowTrackCount,
getSelectedTrackObjects
} from "../selectors";
import { clamp, sort } from "../utils";
import {
REMOVE_TRACKS,
REMOVE_ALL_TRACKS,
REVERSE_LIST,
RANDOMIZE_LIST,
SET_TRACK_ORDER,
SET_PLAYLIST_SCROLL_POSITION,
DRAG_SELECTED
} from "../actionTypes";
export function cropPlaylist() {
return (dispatch, getState) => {
const state = getState();
if (getSelectedTrackObjects(state).length === 0) {
return;
}
const {
playlist: { tracks }
} = getState();
dispatch({
type: REMOVE_TRACKS,
ids: Object.keys(tracks).filter(id => !tracks[id].selected)
});
};
}
export function removeSelectedTracks() {
return (dispatch, getState) => {
const {
playlist: { tracks }
} = getState();
dispatch({
type: REMOVE_TRACKS,
ids: Object.keys(tracks).filter(id => tracks[id].selected)
});
};
}
export function removeAllTracks() {
return { type: REMOVE_ALL_TRACKS };
}
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.playlist.tracks[i].title}`.toLowerCase()
);
return dispatch({ type: SET_TRACK_ORDER, trackOrder });
};
}
export function setPlaylistScrollPosition(position) {
return { type: SET_PLAYLIST_SCROLL_POSITION, position };
}
export function scrollNTracks(n) {
return (dispatch, getState) => {
const state = getState();
const overflow = getOverflowTrackCount(state);
const currentOffset = getScrollOffset(state);
const position = overflow ? clamp((currentOffset + n) / overflow, 0, 1) : 0;
return dispatch({
type: SET_PLAYLIST_SCROLL_POSITION,
position: position * 100
});
};
}
export function scrollPlaylistByDelta(e) {
e.preventDefault();
return (dispatch, getState) => {
const state = getState();
if (getOverflowTrackCount(state)) {
e.stopPropagation();
}
const totalPixelHeight = state.playlist.trackOrder.length * TRACK_HEIGHT;
const percentDelta = (e.deltaY / totalPixelHeight) * 100;
dispatch({
type: SET_PLAYLIST_SCROLL_POSITION,
position: clamp(
state.display.playlistScrollPosition + percentDelta,
0,
100
)
});
};
}
export function scrollUpFourTracks() {
return scrollNTracks(-4);
}
export function scrollDownFourTracks() {
return scrollNTracks(4);
}
function findLastIndex(arr, cb) {
for (let i = arr.length - 1; i >= 0; i--) {
if (cb(arr[i])) {
return i;
}
}
return -1;
}
export function dragSelected(offset) {
return (dispatch, getState) => {
const {
playlist: { trackOrder, tracks }
} = getState();
const firstSelected = trackOrder.findIndex(
trackId => tracks[trackId] && tracks[trackId].selected
);
if (firstSelected === -1) {
return;
}
const lastSelected = findLastIndex(
trackOrder,
trackId => tracks[trackId] && tracks[trackId].selected
);
if (lastSelected === -1) {
throw new Error("We found a first selected, but not a last selected.");
}
// Ensure we don't try to drag off either end.
const min = -firstSelected;
const max = trackOrder.length - 1 - lastSelected;
const normalizedOffset = clamp(offset, min, max);
if (normalizedOffset !== 0) {
dispatch({ type: DRAG_SELECTED, offset: normalizedOffset });
}
};
}