Previewing items to add, in prep for random selection (#546)

This commit is contained in:
James Barnsley
2020-08-01 22:20:07 +12:00
parent 74b73ad6a6
commit 9a09828c20
6 changed files with 347 additions and 94 deletions

View File

@ -439,8 +439,10 @@ modal:
no_editable_playlists: No editable playlists
add_to_queue:
title: Add to queue
subtitle: Add a comma-separated list of URIs to the play queue. You must have the appropriate Mopidy backend enabled for each URI schema (eg spotify:, yt:).
subtitle: Add a comma-separated list of URIs to the play queue
uris: URI(s)
items_to_add: Items to add
no_items: No items
position:
label: Position
end: End

View File

@ -246,7 +246,7 @@ class Queue extends React.Component {
</Link>
<Link className="button button--no-hover" to="/queue/add-uri">
<Icon name="playlist_add" />
<I18n path="now_playing.context_actions.add_uri" />
<I18n path="actions.add" />
</Link>
</span>
);

View File

@ -68,15 +68,25 @@ class LibraryBrowseDirectory extends React.Component {
}
}
loadMore() {
const new_limit = this.state.limit + this.state.per_page;
loadMore = () => {
const {
limit: prevLimit,
per_page,
} = this.state;
const {
history,
location: {
state: prevState = {},
},
} = this.props;
this.setState({ limit: new_limit });
const limit = prevLimit + per_page;
this.setState({ limit });
// Set our pagination to location state
const state = (this.props.location && this.props.location.state ? this.props.location.state : {});
state.limit = new_limit;
this.props.history.replace({ state });
history.replace({
...prevState,
limit,
});
}
playAll(e, tracks) {
@ -150,7 +160,9 @@ class LibraryBrowseDirectory extends React.Component {
uiActions,
view,
} = this.props;
const { limit } = this.state;
const {
limit,
} = this.state;
let title = i18n('library.browse_directory.title');
@ -176,11 +188,11 @@ class LibraryBrowseDirectory extends React.Component {
let subdirectories = (directory.subdirectories && directory.subdirectories.length > 0 ? directory.subdirectories : null);
subdirectories = sortItems(subdirectories, 'name');
const total_items = (tracks ? tracks.length : 0) + (subdirectories ? subdirectories.length : 0);
subdirectories = subdirectories.slice(0, this.state.limit);
const total_items = (directory.tracks ? directory.tracks.length : 0) + (subdirectories ? subdirectories.length : 0);
subdirectories = subdirectories.slice(0, limit);
let all_tracks = null;
let tracks = null;
let limit_remaining = this.state.limit - subdirectories;
const limit_remaining = limit - subdirectories;
if (limit_remaining > 0) {
all_tracks = (directory.tracks && directory.tracks.length > 0 ? directory.tracks : null);
all_tracks = sortItems(all_tracks, 'name');
@ -245,7 +257,7 @@ class LibraryBrowseDirectory extends React.Component {
<LazyLoadListener
loadKey={total_items > limit ? limit : total_items}
showLoader={limit < total_items}
loadMore={() => this.loadMore()}
loadMore={this.loadMore}
/>
</ErrorBoundary>

View File

@ -8,28 +8,108 @@ import * as uiActions from '../../services/ui/actions';
import * as mopidyActions from '../../services/mopidy/actions';
import * as spotifyActions from '../../services/spotify/actions';
import { I18n, i18n } from '../../locale';
import { uriType } from '../../util/helpers';
import Icon from '../../components/Icon';
import TextField from '../../components/Fields/TextField';
const UriListItem = ({
uri,
tracks,
albums,
remove,
}) => {
const type = uriType(uri);
let item = null;
switch (type) {
case 'track':
item = tracks[uri];
break;
case 'album':
item = albums[uri];
break;
default:
break;
}
return (
<div className="list__item">
{item ? item.name : <span className="mid_grey-text">{uri}</span> }
<span className="mid_grey-text"> ({type})</span>
<span className="button discrete remove-uri no-hover" onClick={() => remove(uri)}>
<Icon name="delete" />
<I18n path="actions.remove" />
</span>
</div>
)
}
class AddToQueue extends React.Component {
constructor(props) {
super(props);
this.state = {
uris: '',
text: '',
error: '',
uris: [],
next: false,
};
}
componentDidMount() {
this.props.uiActions.setWindowTitle(i18n('modal.add_to_queue.title'));
const {
uiActions: {
setWindowTitle,
},
} = this.props;
setWindowTitle(i18n('modal.add_to_queue.title'));
}
handleSubmit(e) {
onSubmit = (e) => {
const {
uris,
next,
} = this.state;
const {
mopidyActions: {
enqueueURIs,
},
} = this.props;
e.preventDefault();
const uris = this.state.uris.split(',');
this.props.mopidyActions.enqueueURIs(uris, null, this.state.next);
enqueueURIs(uris, null, next);
window.history.back();
}
render() {
onChange = (text) => {
this.setState({ text });
}
addUris = () => {
const {
text,
} = this.state;
const uris = text.split(',');
this.setState({ uris, text: '' });
}
removeUri = (uri) => {
const {
uris,
} = this.state;
this.setState({ uris: uris.filter((item) => item !== uri) });
}
render = () => {
const {
tracks,
albums,
} = this.props;
const {
uris,
text,
error,
} = this.state;
return (
<Modal className="modal--add-to-queue">
<h1>
@ -39,17 +119,45 @@ class AddToQueue extends React.Component {
<I18n path="modal.add_to_queue.subtitle" />
</h2>
<form onSubmit={(e) => this.handleSubmit(e)}>
<div className="field text">
<form onSubmit={this.onSubmit}>
<div className="field text">
<div className="name">
<I18n path="modal.add_to_queue.uris" />
<I18n path="modal.add_to_queue.items_to_add" />
</div>
<div className="input">
<input
type="text"
onChange={(e) => this.setState({ uris: e.target.value })}
value={this.state.uris}
{uris.length ? (
<div className="list">
{uris.map((uri) => (
<UriListItem
uri={uri}
tracks={tracks}
albums={albums}
remove={this.removeUri}
key={uri}
/>
))}
</div>
) : (
<span className="text grey-text"><I18n path="modal.add_to_queue.no_items" /></span>
)}
</div>
</div>
<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>
@ -96,8 +204,8 @@ class AddToQueue extends React.Component {
const mapStateToProps = (state, ownProps) => ({
mopidy_connected: state.mopidy.connected,
playlist: (state.core.playlists[ownProps.match.params.uri] !== undefined ? state.core.playlists[ownProps.match.params.uri] : null),
playlists: state.core.playlists,
albums: state.core.albums,
tracks: state.core.tracks,
});
const mapDispatchToProps = (dispatch) => ({