mirror of
https://github.com/captbaritone/webamp.git
synced 2026-01-24 02:36:00 +00:00
Support loading multiple files at once
This commit is contained in:
parent
2c0c54102f
commit
302ea6728b
8 changed files with 92 additions and 38 deletions
|
|
@ -20,7 +20,7 @@ import {
|
|||
} from "./utils";
|
||||
import {
|
||||
CLOSE_WINAMP,
|
||||
LOAD_AUDIO_URL,
|
||||
ADD_TRACK_FROM_URL,
|
||||
OPEN_FILE_DIALOG,
|
||||
SEEK_TO_PERCENT_COMPLETE,
|
||||
SET_BALANCE,
|
||||
|
|
@ -44,9 +44,11 @@ import {
|
|||
SET_TRACK_ORDER,
|
||||
TOGGLE_VISUALIZER_STYLE,
|
||||
PLAY_TRACK,
|
||||
BUFFER_TRACK,
|
||||
SET_PLAYLIST_SCROLL_POSITION,
|
||||
DRAG_SELECTED,
|
||||
SET_MEDIA_TAGS
|
||||
SET_MEDIA_TAGS,
|
||||
SET_MEDIA_DURATION
|
||||
} from "./actionTypes";
|
||||
|
||||
function playRandomTrack() {
|
||||
|
|
@ -168,9 +170,18 @@ function setEqFromFile(file) {
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function loadFilesFromReferences(fileReferences) {
|
||||
return dispatch => {
|
||||
Array.from(fileReferences).forEach((file, i) => {
|
||||
dispatch(loadFileFromReference(file, i === 0 ? "PLAY" : "NONE"));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const SKIN_FILENAME_MATCHER = new RegExp("(wsz|zip)$", "i");
|
||||
const EQF_FILENAME_MATCHER = new RegExp("eqf$", "i");
|
||||
export function loadFileFromReference(fileReference) {
|
||||
export function loadFileFromReference(fileReference, priority) {
|
||||
return dispatch => {
|
||||
const file = new MyFile();
|
||||
file.setFileReference(fileReference);
|
||||
|
|
@ -181,25 +192,54 @@ export function loadFileFromReference(fileReference) {
|
|||
} else {
|
||||
const id = uniqueId();
|
||||
const url = URL.createObjectURL(fileReference);
|
||||
dispatch(_loadMediaFromUrl(url, fileReference.name, true, id));
|
||||
dispatch(_addTrackFromUrl(url, fileReference.name, id, priority));
|
||||
dispatch(fetchMediaTags(fileReference, id));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchMediaDuration(url, id) {
|
||||
return dispatch => {
|
||||
// TODO: Does this actually stop downloading the file once it's
|
||||
// got the duration?
|
||||
const audio = document.createElement("audio");
|
||||
const durationChange = () => {
|
||||
const { duration } = audio;
|
||||
dispatch({ type: SET_MEDIA_DURATION, duration, id });
|
||||
audio.removeEventListener("durationchange", durationChange);
|
||||
};
|
||||
audio.addEventListener("durationchange", durationChange);
|
||||
audio.src = url;
|
||||
};
|
||||
}
|
||||
|
||||
let counter = 0;
|
||||
function uniqueId() {
|
||||
return counter++;
|
||||
}
|
||||
|
||||
export function _loadMediaFromUrl(url, name, autoPlay, id) {
|
||||
return { type: LOAD_AUDIO_URL, url, name, autoPlay, id };
|
||||
export function _addTrackFromUrl(url, name, id, priority) {
|
||||
return dispatch => {
|
||||
dispatch({ type: ADD_TRACK_FROM_URL, url, name, id });
|
||||
switch (priority) {
|
||||
case "BUFFER":
|
||||
dispatch({ type: BUFFER_TRACK, name, id });
|
||||
break;
|
||||
case "PLAY":
|
||||
dispatch({ type: PLAY_TRACK, name, id });
|
||||
break;
|
||||
default:
|
||||
// If we're not going to load this right away,
|
||||
// we should fetch duration on our own
|
||||
dispatch(fetchMediaDuration(url, id));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function loadMediaFromUrl(url, name, autoPlay) {
|
||||
export function loadMediaFromUrl(url, name, priority) {
|
||||
return dispatch => {
|
||||
const id = uniqueId();
|
||||
dispatch(_loadMediaFromUrl(url, name, autoPlay, id));
|
||||
dispatch(_addTrackFromUrl(url, name, id, priority));
|
||||
dispatch(fetchMediaTags(url, id));
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
export const LOAD_AUDIO_URL = "LOAD_AUDIO_URL";
|
||||
export const ADD_TRACK_FROM_URL = "ADD_TRACK_FROM_URL";
|
||||
export const CLOSE_WINAMP = "CLOSE_WINAMP";
|
||||
export const CLOSE_EQUALIZER_WINDOW = "CLOSE_EQUALIZER_WINDOW";
|
||||
export const IS_PLAYING = "IS_PLAYING";
|
||||
|
|
@ -56,5 +56,7 @@ export const REVERSE_LIST = "REVERSE_LIST";
|
|||
export const RANDOMIZE_LIST = "RANDOMIZE_LIST";
|
||||
export const SET_TRACK_ORDER = "SET_TRACK_ORDER";
|
||||
export const PLAY_TRACK = "PLAY_TRACK";
|
||||
export const BUFFER_TRACK = "BUFFER_TRACK";
|
||||
export const DRAG_SELECTED = "DRAG_SELECTED";
|
||||
export const SET_MEDIA_TAGS = "SET_MEDIA_TAGS";
|
||||
export const SET_MEDIA_DURATION = "SET_MEDIA_DURATION";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { loadFileFromReference } from "../actionCreators";
|
||||
import { loadFilesFromReferences } from "../actionCreators";
|
||||
|
||||
export class DropTarget extends React.Component {
|
||||
constructor(props) {
|
||||
|
|
@ -17,14 +17,12 @@ export class DropTarget extends React.Component {
|
|||
handleDrop(e) {
|
||||
this.supress(e);
|
||||
const { files } = e.dataTransfer;
|
||||
if (files[0]) {
|
||||
this.props.loadFileFromReference(files[0]);
|
||||
}
|
||||
this.props.loadFilesFromReferences(files);
|
||||
}
|
||||
|
||||
render() {
|
||||
// eslint-disable-next-line no-shadow, no-unused-vars
|
||||
const { loadFileFromReference, ...passThroughProps } = this.props;
|
||||
const { loadFilesFromReferences, ...passThroughProps } = this.props;
|
||||
return (
|
||||
<div
|
||||
{...passThroughProps}
|
||||
|
|
@ -36,4 +34,4 @@ export class DropTarget extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default connect(null, { loadFileFromReference })(DropTarget);
|
||||
export default connect(null, { loadFilesFromReferences })(DropTarget);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ describe("PlaylistShade", () => {
|
|||
});
|
||||
|
||||
it("renders to snapshot", () => {
|
||||
store.dispatch(loadMediaFromUrl("http://example.com", "Some Name", false));
|
||||
store.dispatch(loadMediaFromUrl("http://example.com", "Some Name", "NONE"));
|
||||
const tree = renderer
|
||||
.create(
|
||||
<Provider store={store}>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import {
|
||||
IS_PLAYING,
|
||||
IS_STOPPED,
|
||||
LOAD_AUDIO_URL,
|
||||
PAUSE,
|
||||
PLAY,
|
||||
SEEK_TO_PERCENT_COMPLETE,
|
||||
|
|
@ -15,7 +14,8 @@ import {
|
|||
UPDATE_TIME_ELAPSED,
|
||||
SET_EQ_OFF,
|
||||
SET_EQ_ON,
|
||||
PLAY_TRACK
|
||||
PLAY_TRACK,
|
||||
BUFFER_TRACK
|
||||
} from "./actionTypes";
|
||||
import { next as nextTrack } from "./actionCreators";
|
||||
import { getCurrentTrackId } from "./selectors";
|
||||
|
|
@ -84,12 +84,19 @@ export default media => store => {
|
|||
case SEEK_TO_PERCENT_COMPLETE:
|
||||
media.seekToPercentComplete(action.percent);
|
||||
break;
|
||||
case LOAD_AUDIO_URL:
|
||||
media.loadFromUrl(action.url, action.name, action.autoPlay);
|
||||
break;
|
||||
case PLAY_TRACK:
|
||||
const track = store.getState().playlist.tracks[action.id];
|
||||
media.loadFromUrl(track.url, track.title, true);
|
||||
media.loadFromUrl(
|
||||
store.getState().playlist.tracks[action.id].url,
|
||||
action.name,
|
||||
true
|
||||
);
|
||||
break;
|
||||
case BUFFER_TRACK:
|
||||
media.loadFromUrl(
|
||||
store.getState().playlist.tracks[action.id].url,
|
||||
action.name,
|
||||
false
|
||||
);
|
||||
break;
|
||||
case SET_BAND_VALUE:
|
||||
if (action.band === "preamp") {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import {
|
|||
PLAYLIST_SIZE_CHANGED,
|
||||
SET_AVALIABLE_SKINS,
|
||||
LOAD_AUDIO_FILE,
|
||||
LOAD_AUDIO_URL
|
||||
ADD_TRACK_FROM_URL
|
||||
} from "../actionTypes";
|
||||
|
||||
import playlist from "./playlist";
|
||||
|
|
@ -232,7 +232,7 @@ const media = (state, action) => {
|
|||
case UPDATE_TIME_ELAPSED:
|
||||
return { ...state, timeElapsed: action.elapsed };
|
||||
case LOAD_AUDIO_FILE:
|
||||
case LOAD_AUDIO_URL:
|
||||
case ADD_TRACK_FROM_URL:
|
||||
return {
|
||||
...state,
|
||||
timeElapsed: 0,
|
||||
|
|
|
|||
|
|
@ -8,13 +8,15 @@ import {
|
|||
INVERT_SELECTION,
|
||||
REMOVE_ALL_TRACKS,
|
||||
REMOVE_TRACKS,
|
||||
LOAD_AUDIO_URL,
|
||||
ADD_TRACK_FROM_URL,
|
||||
REVERSE_LIST,
|
||||
RANDOMIZE_LIST,
|
||||
SET_TRACK_ORDER,
|
||||
PLAY_TRACK,
|
||||
BUFFER_TRACK,
|
||||
DRAG_SELECTED,
|
||||
SET_MEDIA_TAGS
|
||||
SET_MEDIA_TAGS,
|
||||
SET_MEDIA_DURATION
|
||||
} from "../actionTypes";
|
||||
|
||||
import { shuffle, moveSelected, mapObject, filterObject } from "../utils";
|
||||
|
|
@ -128,11 +130,10 @@ const playlist = (state = defaultPlaylistState, action) => {
|
|||
case SET_TRACK_ORDER:
|
||||
const { trackOrder } = action;
|
||||
return { ...state, trackOrder };
|
||||
case LOAD_AUDIO_URL:
|
||||
case ADD_TRACK_FROM_URL:
|
||||
return {
|
||||
...state,
|
||||
trackOrder: [...state.trackOrder, Number(action.id)],
|
||||
currentTrack: action.id,
|
||||
tracks: {
|
||||
...state.tracks,
|
||||
[action.id]: {
|
||||
|
|
@ -168,7 +169,19 @@ const playlist = (state = defaultPlaylistState, action) => {
|
|||
}
|
||||
}
|
||||
};
|
||||
case SET_MEDIA_DURATION:
|
||||
return {
|
||||
...state,
|
||||
tracks: {
|
||||
...state.tracks,
|
||||
[action.id]: {
|
||||
...state.tracks[action.id],
|
||||
duration: action.duration
|
||||
}
|
||||
}
|
||||
};
|
||||
case PLAY_TRACK:
|
||||
case BUFFER_TRACK:
|
||||
return {
|
||||
...state,
|
||||
currentTrack: action.id
|
||||
|
|
|
|||
12
js/winamp.js
12
js/winamp.js
|
|
@ -9,7 +9,7 @@ import Media from "./media";
|
|||
import {
|
||||
setSkinFromUrl,
|
||||
loadMediaFromUrl,
|
||||
loadFileFromReference
|
||||
loadFilesFromReferences
|
||||
} from "./actionCreators";
|
||||
|
||||
import { SET_AVALIABLE_SKINS } from "./actionTypes";
|
||||
|
|
@ -34,9 +34,7 @@ class Winamp {
|
|||
);
|
||||
|
||||
this.fileInput.addEventListener("change", e => {
|
||||
if (e.target.files[0]) {
|
||||
this.store.dispatch(loadFileFromReference(e.target.files[0], true));
|
||||
}
|
||||
this.store.dispatch(loadFilesFromReferences(e.target.files));
|
||||
});
|
||||
|
||||
if (this.options.initialTrack && this.options.initialTrack.url) {
|
||||
|
|
@ -44,7 +42,7 @@ class Winamp {
|
|||
loadMediaFromUrl(
|
||||
this.options.initialTrack.url,
|
||||
this.options.initialTrack.name,
|
||||
false
|
||||
"BUFFER"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -58,10 +56,6 @@ class Winamp {
|
|||
|
||||
new Hotkeys(this.fileInput, this.store);
|
||||
}
|
||||
|
||||
loadTrackUrl(url, name) {
|
||||
this.store.dispatch(loadMediaFromUrl(url, name));
|
||||
}
|
||||
}
|
||||
|
||||
export default Winamp;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue