2017-03-08 09:13:24 +13:00
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
import React from 'react';
|
|
|
|
|
import { connect } from 'react-redux';
|
|
|
|
|
import { bindActionCreators } from 'redux';
|
2018-07-09 19:09:12 +12:00
|
|
|
import Modal from './Modal';
|
2019-09-05 15:36:11 +12:00
|
|
|
import * as coreActions from '../../services/core/actions';
|
|
|
|
|
import * as uiActions from '../../services/ui/actions';
|
|
|
|
|
import * as mopidyActions from '../../services/mopidy/actions';
|
|
|
|
|
import * as spotifyActions from '../../services/spotify/actions';
|
2020-07-19 20:41:14 +12:00
|
|
|
import { I18n, i18n } from '../../locale';
|
2020-08-01 22:20:07 +12:00
|
|
|
import { uriType } from '../../util/helpers';
|
|
|
|
|
import Icon from '../../components/Icon';
|
|
|
|
|
import TextField from '../../components/Fields/TextField';
|
2020-08-03 07:08:16 +12:00
|
|
|
import LinksSentence from '../../components/LinksSentence';
|
2020-08-16 20:00:10 +12:00
|
|
|
import Button from '../../components/Button';
|
2020-08-01 22:20:07 +12:00
|
|
|
|
|
|
|
|
const UriListItem = ({
|
|
|
|
|
uri,
|
2020-09-11 22:13:06 +12:00
|
|
|
items,
|
2020-08-03 20:42:17 +12:00
|
|
|
random_tracks,
|
2020-08-01 22:20:07 +12:00
|
|
|
remove,
|
|
|
|
|
}) => {
|
|
|
|
|
const type = uriType(uri);
|
2020-09-11 22:13:06 +12:00
|
|
|
let item = items[uri];
|
2020-08-03 20:42:17 +12:00
|
|
|
if (!item) {
|
|
|
|
|
item = random_tracks.find((track) => track.uri === uri);
|
|
|
|
|
}
|
2020-08-01 22:20:07 +12:00
|
|
|
return (
|
2020-08-03 07:08:16 +12:00
|
|
|
<div className="list__item list__item--no-interaction">
|
|
|
|
|
{item ? item.name : <span className="mid_grey-text">{uri}</span>}
|
|
|
|
|
{item && item.artists && (
|
|
|
|
|
<I18n path="common.by" contentAfter>
|
2021-01-09 22:52:45 +13:00
|
|
|
<LinksSentence nolinks items={item.artists} type="artist" />
|
2020-08-03 07:08:16 +12:00
|
|
|
</I18n>
|
|
|
|
|
)}
|
|
|
|
|
<span className="mid_grey-text">{` (${type})`}</span>
|
2020-08-16 20:00:10 +12:00
|
|
|
<Button
|
|
|
|
|
type="destructive"
|
|
|
|
|
discrete
|
|
|
|
|
size="tiny"
|
|
|
|
|
className="pull-right"
|
2020-08-03 07:08:16 +12:00
|
|
|
onClick={() => remove(uri)}
|
2020-08-16 20:00:10 +12:00
|
|
|
tracking={{ category: 'AddToQueue', action: 'RemoveItem' }}
|
2020-08-03 07:08:16 +12:00
|
|
|
>
|
2020-08-01 22:20:07 +12:00
|
|
|
<Icon name="delete" />
|
|
|
|
|
<I18n path="actions.remove" />
|
2020-08-16 20:00:10 +12:00
|
|
|
</Button>
|
2020-08-01 22:20:07 +12:00
|
|
|
</div>
|
2020-08-03 07:08:16 +12:00
|
|
|
);
|
|
|
|
|
};
|
2017-03-08 09:13:24 +13:00
|
|
|
|
2020-03-03 16:39:37 +13:00
|
|
|
class AddToQueue extends React.Component {
|
2019-09-05 15:36:11 +12:00
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = {
|
2020-08-01 22:20:07 +12:00
|
|
|
text: '',
|
|
|
|
|
error: '',
|
2019-09-05 15:36:11 +12:00
|
|
|
next: false,
|
|
|
|
|
};
|
|
|
|
|
}
|
2017-03-08 09:13:24 +13:00
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
componentDidMount() {
|
2020-08-01 22:20:07 +12:00
|
|
|
const {
|
|
|
|
|
uiActions: {
|
|
|
|
|
setWindowTitle,
|
|
|
|
|
},
|
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
|
|
setWindowTitle(i18n('modal.add_to_queue.title'));
|
2019-09-05 15:36:11 +12:00
|
|
|
}
|
2017-03-08 09:13:24 +13:00
|
|
|
|
2020-08-01 22:20:07 +12:00
|
|
|
onSubmit = (e) => {
|
|
|
|
|
const {
|
|
|
|
|
next,
|
|
|
|
|
} = this.state;
|
|
|
|
|
const {
|
|
|
|
|
mopidyActions: {
|
|
|
|
|
enqueueURIs,
|
|
|
|
|
},
|
2020-08-03 20:42:17 +12:00
|
|
|
view: {
|
|
|
|
|
uris = [],
|
|
|
|
|
},
|
2020-08-01 22:20:07 +12:00
|
|
|
} = this.props;
|
|
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
e.preventDefault();
|
2020-08-01 22:20:07 +12:00
|
|
|
enqueueURIs(uris, null, next);
|
2020-08-03 20:42:17 +12:00
|
|
|
this.reset();
|
2019-09-05 15:36:11 +12:00
|
|
|
window.history.back();
|
|
|
|
|
}
|
2018-07-13 16:48:41 +12:00
|
|
|
|
2020-08-01 22:20:07 +12:00
|
|
|
onChange = (text) => {
|
|
|
|
|
this.setState({ text });
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-03 20:42:17 +12:00
|
|
|
reset = () => {
|
|
|
|
|
const {
|
|
|
|
|
coreActions: {
|
|
|
|
|
viewDataLoaded,
|
|
|
|
|
},
|
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
|
|
viewDataLoaded({ uris: [], random_tracks: [] });
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-03 07:08:16 +12:00
|
|
|
addRandom = () => {
|
|
|
|
|
const {
|
|
|
|
|
mopidyActions: {
|
2020-08-03 20:42:17 +12:00
|
|
|
view_getRandomTracks,
|
2020-08-03 07:08:16 +12:00
|
|
|
},
|
|
|
|
|
} = this.props;
|
|
|
|
|
|
2020-08-03 20:42:17 +12:00
|
|
|
view_getRandomTracks(20);
|
2020-08-03 07:08:16 +12:00
|
|
|
}
|
|
|
|
|
|
2020-08-01 22:20:07 +12:00
|
|
|
addUris = () => {
|
|
|
|
|
const {
|
|
|
|
|
text,
|
|
|
|
|
} = this.state;
|
2020-08-03 07:08:16 +12:00
|
|
|
const {
|
2020-08-03 20:42:17 +12:00
|
|
|
view: {
|
|
|
|
|
uris: prevUris = [],
|
|
|
|
|
},
|
2020-08-03 07:08:16 +12:00
|
|
|
coreActions: {
|
|
|
|
|
loadItem,
|
2020-08-03 20:42:17 +12:00
|
|
|
viewDataLoaded,
|
2020-08-03 07:08:16 +12:00
|
|
|
},
|
|
|
|
|
} = this.props;
|
2020-08-01 22:20:07 +12:00
|
|
|
const uris = text.split(',');
|
2020-08-03 07:08:16 +12:00
|
|
|
|
|
|
|
|
const validatedUris = uris.filter((uri) => uriType(uri));
|
|
|
|
|
validatedUris.forEach((uri) => {
|
|
|
|
|
loadItem(uri);
|
|
|
|
|
});
|
|
|
|
|
|
2020-08-03 20:42:17 +12:00
|
|
|
this.setState({ text: '' });
|
2020-09-27 21:07:06 +13:00
|
|
|
viewDataLoaded({ uris: [...prevUris, ...uris] }); // We add all uris (validated and otherwise)
|
2020-08-01 22:20:07 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
removeUri = (uri) => {
|
|
|
|
|
const {
|
2020-08-03 20:42:17 +12:00
|
|
|
view: {
|
|
|
|
|
uris = [],
|
|
|
|
|
},
|
|
|
|
|
coreActions: {
|
|
|
|
|
viewDataLoaded,
|
|
|
|
|
},
|
|
|
|
|
} = this.props;
|
2020-08-01 22:20:07 +12:00
|
|
|
|
2020-08-03 20:42:17 +12:00
|
|
|
viewDataLoaded({ uris: uris.filter((item) => item !== uri) });
|
2020-08-01 22:20:07 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render = () => {
|
|
|
|
|
const {
|
2020-09-11 22:13:06 +12:00
|
|
|
items,
|
2020-08-03 20:42:17 +12:00
|
|
|
view: {
|
|
|
|
|
uris = [],
|
|
|
|
|
random_tracks = [],
|
|
|
|
|
},
|
2020-08-01 22:20:07 +12:00
|
|
|
} = this.props;
|
|
|
|
|
const {
|
|
|
|
|
text,
|
|
|
|
|
error,
|
2020-08-03 07:08:16 +12:00
|
|
|
next,
|
2020-08-01 22:20:07 +12:00
|
|
|
} = this.state;
|
|
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
return (
|
|
|
|
|
<Modal className="modal--add-to-queue">
|
2020-07-19 20:41:14 +12:00
|
|
|
<h1>
|
2020-08-03 07:08:16 +12:00
|
|
|
<I18n path="modal.add_to_queue.title" />
|
2020-07-19 20:41:14 +12:00
|
|
|
</h1>
|
|
|
|
|
<h2 className="mid_grey-text">
|
|
|
|
|
<I18n path="modal.add_to_queue.subtitle" />
|
|
|
|
|
</h2>
|
2017-03-08 09:13:24 +13:00
|
|
|
|
2020-08-01 22:20:07 +12:00
|
|
|
<form onSubmit={this.onSubmit}>
|
|
|
|
|
|
2020-08-03 07:08:16 +12:00
|
|
|
<div className="field text">
|
|
|
|
|
<div className="name">
|
|
|
|
|
<I18n path="fields.uri" />
|
|
|
|
|
</div>
|
|
|
|
|
<div className="input">
|
|
|
|
|
<TextField
|
|
|
|
|
onChange={this.onChange}
|
|
|
|
|
value={text}
|
|
|
|
|
/>
|
|
|
|
|
<span className="button discrete add-uri no-hover" onClick={this.addUris}>
|
|
|
|
|
<Icon name="add" />
|
|
|
|
|
<I18n path="actions.add" />
|
|
|
|
|
</span>
|
|
|
|
|
{error && <span className="description error">{error}</span>}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="field text">
|
2020-08-01 22:20:07 +12:00
|
|
|
<div className="name">
|
2020-08-03 07:08:16 +12:00
|
|
|
<I18n path="fields.items_to_add.label" />
|
2020-08-01 22:20:07 +12:00
|
|
|
</div>
|
|
|
|
|
<div className="input">
|
|
|
|
|
{uris.length ? (
|
|
|
|
|
<div className="list">
|
2020-08-03 07:08:16 +12:00
|
|
|
{uris.map((uri, index) => (
|
2020-08-01 22:20:07 +12:00
|
|
|
<UriListItem
|
|
|
|
|
uri={uri}
|
2020-09-11 22:13:06 +12:00
|
|
|
items={items}
|
2020-08-03 20:42:17 +12:00
|
|
|
random_tracks={random_tracks}
|
2020-08-01 22:20:07 +12:00
|
|
|
remove={this.removeUri}
|
2020-08-03 07:08:16 +12:00
|
|
|
key={`${uri}_${index}`}
|
2020-08-01 22:20:07 +12:00
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
2020-08-03 07:08:16 +12:00
|
|
|
<span className="text mid_grey-text">
|
|
|
|
|
<I18n path="fields.items_to_add.placeholder" />
|
|
|
|
|
</span>
|
2020-08-01 22:20:07 +12:00
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
<div className="field radio white">
|
|
|
|
|
<div className="name">
|
2020-08-03 07:08:16 +12:00
|
|
|
<I18n path="modal.add_to_queue.position.label" />
|
2019-09-05 15:36:11 +12:00
|
|
|
</div>
|
|
|
|
|
<div className="input">
|
|
|
|
|
<label>
|
|
|
|
|
<input
|
|
|
|
|
type="radio"
|
|
|
|
|
name="next"
|
2020-08-03 07:08:16 +12:00
|
|
|
checked={!next}
|
|
|
|
|
onChange={() => this.setState({ next: false })}
|
2019-09-05 15:36:11 +12:00
|
|
|
/>
|
2020-07-19 20:41:14 +12:00
|
|
|
<span className="label">
|
|
|
|
|
<I18n path="modal.add_to_queue.position.end" />
|
|
|
|
|
</span>
|
2019-09-05 15:36:11 +12:00
|
|
|
</label>
|
|
|
|
|
<label>
|
|
|
|
|
<input
|
|
|
|
|
type="radio"
|
|
|
|
|
name="next"
|
2020-08-03 07:08:16 +12:00
|
|
|
checked={next}
|
|
|
|
|
onChange={() => this.setState({ next: true })}
|
2019-09-05 15:36:11 +12:00
|
|
|
/>
|
2020-07-19 20:41:14 +12:00
|
|
|
<span className="label">
|
|
|
|
|
<I18n path="modal.add_to_queue.position.next" />
|
|
|
|
|
</span>
|
2019-09-05 15:36:11 +12:00
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2017-03-08 09:13:24 +13:00
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
<div className="actions centered-text">
|
2020-08-16 20:00:10 +12:00
|
|
|
<Button
|
|
|
|
|
colour="grey"
|
|
|
|
|
size="large"
|
2020-08-03 07:08:16 +12:00
|
|
|
onClick={this.addRandom}
|
2020-08-16 20:00:10 +12:00
|
|
|
tracking={{ category: 'AddToQueue', action: 'AddRandom' }}
|
2020-08-03 07:08:16 +12:00
|
|
|
>
|
|
|
|
|
<I18n path="modal.add_to_queue.add_random" />
|
2020-08-16 20:00:10 +12:00
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
type="primary"
|
|
|
|
|
size="large"
|
2020-08-03 20:42:17 +12:00
|
|
|
disabled={!uris.length}
|
2020-08-16 20:00:10 +12:00
|
|
|
submit
|
|
|
|
|
tracking={{ category: 'AddToQueue', action: 'Submit' }}
|
2020-08-03 20:42:17 +12:00
|
|
|
>
|
2020-07-19 20:41:14 +12:00
|
|
|
<I18n path="actions.add" />
|
2020-08-16 20:00:10 +12:00
|
|
|
</Button>
|
2019-09-05 15:36:11 +12:00
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
</Modal>
|
|
|
|
|
);
|
|
|
|
|
}
|
2018-07-09 19:09:12 +12:00
|
|
|
}
|
|
|
|
|
|
2020-08-03 07:08:16 +12:00
|
|
|
const mapStateToProps = (state) => ({
|
2020-09-11 22:13:06 +12:00
|
|
|
items: state.core.items,
|
2020-08-03 20:42:17 +12:00
|
|
|
view: state.core.view ? state.core.view : {},
|
2019-09-05 15:36:11 +12:00
|
|
|
});
|
2018-07-09 19:09:12 +12:00
|
|
|
|
2019-09-05 15:36:11 +12:00
|
|
|
const mapDispatchToProps = (dispatch) => ({
|
|
|
|
|
coreActions: bindActionCreators(coreActions, dispatch),
|
|
|
|
|
uiActions: bindActionCreators(uiActions, dispatch),
|
|
|
|
|
mopidyActions: bindActionCreators(mopidyActions, dispatch),
|
|
|
|
|
spotifyActions: bindActionCreators(spotifyActions, dispatch),
|
|
|
|
|
});
|
2018-07-09 19:09:12 +12:00
|
|
|
|
2020-03-03 16:39:37 +13:00
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(AddToQueue);
|