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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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) => ({