Removing remaining artistLoaded, albumLoaded, etc in favor of itemLoaded for consistent pipeline; Looking at search

This commit is contained in:
James Barnsley
2020-09-13 20:59:46 +12:00
parent f254170b2f
commit 449b32a384
30 changed files with 579 additions and 465 deletions

View File

@ -37,7 +37,7 @@ class DebugInfo extends React.Component {
};
}
renderLoadQueue() {
renderload_queue() {
const { ui: { load_queue } } = this.props;
if (!load_queue) return <div className="debug-info-item mid_grey-text">Nothing loading</div>;
@ -171,7 +171,7 @@ kb (~
<div className="debug-info-section">
<h5>Load queue</h5>
{this.renderLoadQueue()}
{this.renderload_queue()}
</div>
</div>

View File

@ -57,21 +57,20 @@ class AddSeedField extends React.Component {
);
}
handleSelect(e, item) {
handleSelect = (e, item) => {
const {
onSelect,
spotifyActions: {
clearAutocompleteResults,
},
coreActions: {
itemLoaded,
},
} = this.props;
this.setState({ value: '' });
this.props.onSelect(e, item.uri);
this.props.spotifyActions.clearAutocompleteResults(this.id);
// Add our selected item to our global index
switch (uriType(item.uri)) {
case 'artist':
this.props.coreActions.artistsLoaded(item);
break;
case 'track':
this.props.coreActions.tracksLoaded(item);
break;
}
onSelect(e, item.uri);
clearAutocompleteResults(this.id);
itemLoaded(item);
}
results() {

View File

@ -20,7 +20,7 @@ export default class ListItem extends React.Component {
}
componentDidMount() {
const { item, lastfmActions, discogsActions } = this.props;
const { item, mopidyActions, discogsActions } = this.props;
if (!item) return;
// If the item that has just been mounted doesn't have images,
@ -29,13 +29,13 @@ export default class ListItem extends React.Component {
switch (uriType(item.uri)) {
case 'artist':
if (discogsActions) {
discogsActions.getArtistImages(item.uri, item);
//discogsActions.getArtistImages(item.uri, item);
}
break;
case 'album':
if (lastfmActions && item.artists && item.artists.length > 0) {
lastfmActions.getAlbum(item.uri, item.artists[0].name, item.name, (item.mbid ? item.mbid : null));
if (mopidyActions) {
mopidyActions.getImages([item.uri]);
}
break;
}

View File

@ -2,7 +2,7 @@
import React from 'react';
import { connect } from 'react-redux';
import { titleCase, getIndexedRecords } from '../util/helpers';
import { sortItems } from '../util/arrays';
import { sortItems, indexToArray } from '../util/arrays';
import URILink from './URILink';
import Icon from './Icon';
import AlbumGrid from './AlbumGrid';
@ -17,7 +17,7 @@ const SearchResults = ({
type,
query,
loadMore,
index,
items,
mopidy_search_results,
spotify_search_results,
sort,
@ -39,7 +39,7 @@ const SearchResults = ({
...(
type === 'tracks'
? mopidy_search_results[type]
: getIndexedRecords(index, mopidy_search_results[type])
: indexToArray(items, mopidy_search_results[type])
),
];
}
@ -50,7 +50,7 @@ const SearchResults = ({
...(
type === 'tracks'
? spotify_search_results[type]
: getIndexedRecords(index, spotify_search_results[type])
: indexToArray(items, spotify_search_results[type])
),
];
}
@ -120,8 +120,8 @@ const SearchResults = ({
);
};
const mapStateToProps = (state, ownProps) => ({
index: state.core[ownProps.type] || [],
const mapStateToProps = (state) => ({
items: state.core.items,
uri_schemes_priority: state.ui.uri_schemes_priority || [],
mopidy_search_results: state.mopidy.search_results || {},
spotify_search_results: state.spotify.search_results || {},

View File

@ -315,7 +315,7 @@ const CoreMiddleware = (function () {
* */
case 'LOAD_ITEMS':
action.uris.forEach((uri) => {
store.dispatch(uiActions.startLoading(uri, `load_item_${uri}`));
store.dispatch(uiActions.startLoading(uri));
store.dispatch({
type: `LOAD_${uriType(uri).toUpperCase()}`,
uri,
@ -350,7 +350,8 @@ const CoreMiddleware = (function () {
store.getState().core.items[action.uri]
&& store.getState().core.items[action.uri].images
) {
console.info(`Using "${action.uri}" from index`);
console.info(`${action.uri}" already in index`);
store.dispatch(uiActions.stopLoading(action.uri));
break;
}
@ -397,7 +398,8 @@ const CoreMiddleware = (function () {
store.getState().core.items[action.uri]
&& (!action.options.full || store.getState().core.items[action.uri].tracks)
) {
console.info(`Using "${action.uri}" from index`);
console.info(`${action.uri}" already in index`);
store.dispatch(uiActions.stopLoading(action.uri));
break;
}
@ -419,6 +421,7 @@ const CoreMiddleware = (function () {
break;
case 'LOAD_ARTIST':
console.log(action);
const fetchArtist = () => {
switch (uriSource(action.uri)) {
case 'spotify':
@ -451,7 +454,9 @@ const CoreMiddleware = (function () {
)
)
) {
console.info(`Using "${action.uri}" from index`);
console.info(`${action.uri}" already in index`);
store.dispatch(coreActions.loadItems(store.getState().core.items[action.uri].albums_uris));
store.dispatch(uiActions.stopLoading(action.uri));
break;
}
@ -507,7 +512,8 @@ const CoreMiddleware = (function () {
|| store.getState().core.items[action.uri].tracks
)
) {
console.info(`Using "${action.uri}" from index`);
console.info(`${action.uri}" already in index`);
store.dispatch(uiActions.stopLoading(action.uri));
break;
}
@ -575,7 +581,7 @@ const CoreMiddleware = (function () {
break;
case 'LOAD_LIBRARY':
store.dispatch(uiActions.startLoading(action.uri, `load_library_${action.uri}`));
store.dispatch(uiActions.startLoading(action.uri));
const fetchLibrary = () => {
switch (uriSource(action.uri)) {
case 'spotify':
@ -602,7 +608,8 @@ const CoreMiddleware = (function () {
break;
}
if (store.getState().core.libraries[action.uri]) {
console.info(`Using "${action.uri}" from index`);
console.info(`${action.uri}" already in index`);
store.dispatch(uiActions.stopLoading(action.uri));
break;
}
@ -612,10 +619,12 @@ const CoreMiddleware = (function () {
const promises = library.items_uris.map((libraryItem) => localForage.getItem(libraryItem));
Promise.all(promises).then(
(libraryItems) => store.dispatch(coreActions.restoreItemsFromColdStore(compact(libraryItems))),
(libraryItems) => {
store.dispatch(coreActions.restoreItemsFromColdStore(compact(libraryItems)));
store.dispatch(coreActions.restoreLibraryFromColdStore(library));
},
);
store.dispatch(coreActions.restoreLibraryFromColdStore(library));
} else {
fetchLibrary();
}
@ -720,10 +729,10 @@ const CoreMiddleware = (function () {
action.albums = albums_loaded;
if (artists_loaded.length > 0) {
store.dispatch(coreActions.artistsLoaded(artists_loaded));
store.dispatch(coreActions.items(artists_loaded));
}
if (tracks_loaded.length > 0) {
store.dispatch(coreActions.tracksLoaded(tracks_loaded));
store.dispatch(coreActions.items(tracks_loaded));
}
store.dispatch(coreActions.updateColdStore(albums_loaded));

View File

@ -1,5 +1,6 @@
import { generateGuid } from '../../util/helpers';
import { formatArtist } from '../../util/format';
const coreActions = require('../core/actions');
const uiActions = require('../ui/actions');
@ -58,11 +59,10 @@ export function getArtistImages(uri, artist) {
(response) => {
if (response) {
if (response.results.length > 0 && response.results[0].cover_image !== undefined) {
const updated_artist = {
dispatch(coreActions.itemLoaded(formatArtist({
uri,
images: [response.results[0].cover_image],
};
dispatch(coreActions.artistLoaded(updated_artist));
})));
} else {
console.log(`Discogs: No results for artist ${artist.name}`);
}

View File

@ -332,7 +332,9 @@ export function getImages(context, uri) {
.then(
(response) => {
if (response.album) {
dispatch(coreActions.albumLoaded({ uri, images: response.album.image }));
dispatch(
coreActions.itemLoaded(formatAlbum({ uri, images: response.album.image })),
);
}
},
);

View File

@ -12,6 +12,7 @@ import {
import {
digestMopidyImages,
formatImages,
formatAlbums,
formatTrack,
formatTracks,
formatSimpleObject,
@ -1094,7 +1095,7 @@ const MopidyMiddleware = (function () {
let albums_uris = arrayOf('uri', albums);
albums_uris = removeDuplicates(albums_uris);
store.dispatch(coreActions.albumsLoaded(albums));
store.dispatch(coreActions.itemsLoaded(albums));
// and plug in their URIs
store.dispatch({
@ -1169,11 +1170,7 @@ const MopidyMiddleware = (function () {
}
artists_uris = removeDuplicates(artists_uris);
// load each artist
for (var i = 0; i < artists_uris.length; i++) {
store.dispatch(mopidyActions.getArtist(artists_uris[i]));
}
store.dispatch(coreActions.loadItems(artists_uris));
// and plug in their URIs
store.dispatch({
@ -1380,7 +1377,7 @@ const MopidyMiddleware = (function () {
let albums_uris = arrayOf('uri', albums);
albums_uris = removeDuplicates(albums_uris);
store.dispatch(coreActions.albumsLoaded(albums));
store.dispatch(coreActions.itemsLoaded(formatAlbums(albums)));
// and plug in their URIs
store.dispatch({
@ -1446,11 +1443,7 @@ const MopidyMiddleware = (function () {
}
artists_uris = removeDuplicates(artists_uris);
// load each artist
for (var i = 0; i < artists_uris.length; i++) {
store.dispatch(mopidyActions.getArtist(artists_uris[i]));
}
store.dispatch(coreActions.loadItems(artists_uris));
// and plug in their URIs
store.dispatch({
@ -1676,7 +1669,7 @@ const MopidyMiddleware = (function () {
store.dispatch(coreActions.addPinned(playlist));
}
store.dispatch(coreActions.playlistLoaded(playlist));
store.dispatch(coreActions.itemLoaded(playlist));
store.dispatch(uiActions.createNotification({ content: 'Playlist saved' }));
});
});
@ -1726,7 +1719,7 @@ const MopidyMiddleware = (function () {
request(store, 'playlists.create', { name: action.name, uri_scheme: action.scheme })
.then((response) => {
store.dispatch(uiActions.createNotification({ content: 'Created playlist' }));
store.dispatch(coreActions.playlistLoaded(response));
store.dispatch(coreActions.itemLoaded(response));
store.dispatch({
type: 'MOPIDY_LIBRARY_PLAYLIST_CREATED',
key: response.uri,
@ -1807,6 +1800,7 @@ const MopidyMiddleware = (function () {
break;
case 'MOPIDY_GET_ARTIST':
console.log(action);
request(store, 'library.lookup', { uris: [action.uri] })
.then((_response) => {
if (!_response) return;
@ -1876,7 +1870,7 @@ const MopidyMiddleware = (function () {
provider: 'mopidy',
}));
store.dispatch(coreActions.artistsLoaded(artists));
store.dispatch(coreActions.itemsLoaded(artists));
// Re-run any consequential processes in 100ms. This allows a small window for other
// server requests before our next batch. It's a little crude but it means the server isn't
@ -2084,6 +2078,7 @@ const MopidyMiddleware = (function () {
request(store, 'library.browse', { uri: action.uri })
.then((response) => {
const tracks_uris = [];
const tracks = [];
const subdirectories = [];
for (const item of response) {
@ -2125,8 +2120,6 @@ const MopidyMiddleware = (function () {
return;
}
const tracks = [];
for (const uri in response) {
if (response.hasOwnProperty(uri) && response[uri].length > 0) {
tracks.push(formatTrack(response[uri][0]));

View File

@ -678,19 +678,19 @@ export function getAutocompleteResults(field_id, query, types = ['album', 'artis
}
if (response.artists && response.artists.items) {
dispatch(coreActions.artistsLoaded(response.artists.items));
dispatch(coreActions.itemsLoaded(response.artists.items));
}
if (response.albums && response.albums.items) {
dispatch(coreActions.albumsLoaded(response.albums.items));
dispatch(coreActions.itemsLoaded(response.albums.items));
}
if (response.playlists && response.playlists.items) {
dispatch(coreActions.playlistsLoaded(response.playlists.items));
dispatch(coreActions.itemsLoaded(response.playlists.items));
}
if (response.tracks && response.tracks.items) {
dispatch(coreActions.tracksLoaded(response.tracks.items));
dispatch(coreActions.itemsLoaded(response.tracks.items));
}
dispatch({

View File

@ -121,6 +121,7 @@ const SpotifyMiddleware = (function () {
next(action);
break;
// TODO: This can go
case 'SPOTIFY_ARTIST_ALBUMS_LOADED':
store.dispatch(coreActions.albumsLoaded(action.data.items));
store.dispatch({

View File

@ -124,7 +124,7 @@ export default function reducer(ui = {}, action) {
case 'START_LOADING':
var load_queue = { ...(ui.load_queue ? ui.load_queue : {}) };
load_queue[action.key] = action.source;
load_queue[action.key] = action.source || action.key;
return { ...ui, load_queue };
case 'STOP_LOADING':

View File

@ -209,6 +209,7 @@ const uiPersistConfig = {
key: 'ui',
storage: localForage,
blacklist: [
'debug_response',
'load_queue',
'notifications',
'processes',

View File

@ -369,20 +369,26 @@ let isObject = function (value) {
* @param key = string (the string to lookup)
* @return boolean
* */
const isLoading = function (load_queue = [], keys = []) {
// Loop all of our load queue items
for (const load_queue_key in load_queue) {
// Make sure it's not a root object method
if (load_queue.hasOwnProperty(load_queue_key)) {
// Loop all the keys we're looking for
for (let i = 0; i < keys.length; i++) {
if (load_queue[load_queue_key].includes(keys[i])) {
return true;
}
}
const isLoading = function (load_queue = {}, keys = []) {
if (!load_queue || !keys) return false;
const queue_keys = Object.keys(load_queue);
const matches = keys.reduce((acc, key) => {
let regex = '';
try {
regex = new RegExp(key);
} catch {
console.error('Invalid regular expression', keys);
return acc;
}
}
return false;
return [
...acc,
...(queue_keys.filter((qk) => qk.match(regex))),
];
}, []);
return matches.length > 0;
};

View File

@ -171,9 +171,7 @@ export class Album extends React.Component {
if (!album) {
if (
isLoading(load_queue, [
`spotify_albums/${getFromUri('albumid', uri)}`,
])
isLoading(load_queue, [`(.*)${uri}`])
) {
return <Loader body loading />;
}

View File

@ -197,10 +197,6 @@ class Artist extends React.Component {
value: 'single',
label: i18n('artist.albums.filter.singles'),
},
{
value: 'compilation',
label: i18n('artist.albums.filter.compilations'),
},
];
return (
@ -402,10 +398,7 @@ class Artist extends React.Component {
if (!artist) {
if (
isLoading(
load_queue,
[`spotify_artists/${getFromUri('artistid', uri)}`, 'lastfm_method=artist.getInfo'],
)
isLoading(load_queue, [`(.*)${uri}(.*)`])
) {
return <Loader body loading />;
}

View File

@ -279,7 +279,7 @@ class Playlist extends React.Component {
const playlist_id = getFromUri('playlistid', uri);
if (!playlist) {
if (isLoading(load_queue, [`spotify_playlists/${playlist_id}?`])) {
if (isLoading(load_queue, [`(.*)${playlist_id}`])) {
return <Loader body loading />
}
return (
@ -349,7 +349,7 @@ class Playlist extends React.Component {
{this.renderActions()}
{isLoading(load_queue, [`spotify_playlists/${playlist_id}/tracks`]) ? (
{isLoading(load_queue, [`(.*)${playlist_id}/tracks`]) ? (
<Loader body loading />
) : (
<section className="list-wrapper">

View File

@ -377,10 +377,6 @@ const mapStateToProps = (state) => {
spotify_enabled: state.spotify.enabled,
radio: state.core.radio,
radio_enabled: !!(state.core.radio && state.core.radio.enabled),
artists: state.core.artists,
albums: state.core.albums,
playlists: state.core.playlists,
tracks: state.core.tracks,
items,
queue_tracks,
current_track_uri: state.core.current_track_uri,

View File

@ -46,6 +46,7 @@ class Search extends React.Component {
// Auto-focus on the input field
$(document).find('.search-form input').focus();
this.digestUri();
}
componentDidUpdate = ({
@ -61,13 +62,7 @@ class Search extends React.Component {
} = this.props;
const { type, term } = this.state;
// Already connected, but search properties changed
if (prev_mopidy_connected && mopidy_connected) {
if (prevType !== typeProp || prevTerm !== termProp) {
this.digestUri();
}
// Connected
} else if (!prev_mopidy_connected && mopidy_connected && uri_schemes_search_enabled) {
if (prevType !== typeProp || prevTerm !== termProp) {
this.search(type, term);
}
}
@ -148,7 +143,6 @@ class Search extends React.Component {
uiActions: {
setWindowTitle,
},
mopidy_connected,
uri_schemes_search_enabled,
mopidyActions,
spotifyActions,
@ -174,7 +168,7 @@ class Search extends React.Component {
setWindowTitle(i18n('search.title_window', { term: decodeURIComponent(term) }));
if (type && term && mopidy_connected && uri_schemes_search_enabled) {
if (type && term) {
if (mopidyTerm !== term || mopidyType !== type) {
mopidyActions.clearSearchResults();
mopidyActions.getSearchResults(type, term);
@ -324,7 +318,6 @@ class Search extends React.Component {
const mapStateToProps = (state, ownProps) => ({
type: ownProps.match.params.type,
term: ownProps.match.params.term,
mopidy_connected: state.mopidy.connected,
albums: (state.core.albums ? state.core.albums : []),
artists: (state.core.artists ? state.core.artists : []),
playlists: (state.core.playlists ? state.core.playlists : []),

View File

@ -18,6 +18,8 @@ import { sortItems, applyFilter } from '../../util/arrays';
import { collate } from '../../util/format';
import Button from '../../components/Button';
import { i18n, I18n } from '../../locale';
import { isLoading } from '../../util/helpers';
import Loader from '../../components/Loader';
class LibraryAlbums extends React.Component {
constructor(props) {
@ -175,12 +177,17 @@ class LibraryAlbums extends React.Component {
sort,
sort_reverse,
view,
load_queue,
} = this.props;
const {
limit,
filter,
} = this.state;
if (isLoading(load_queue, ['(.*):library:albums'])) {
return <Loader body loading />;
}
let albums = [
...(source === 'all' || source === 'spotify' ? collate(spotify_library, { items }).items : []),
...(source === 'all' || source === 'google' ? collate(google_library, { items }).items : []),

View File

@ -12,12 +12,13 @@ import Icon from '../../components/Icon';
import * as uiActions from '../../services/ui/actions';
import * as coreActions from '../../services/core/actions';
import {
uriSource,
uriSource, isLoading,
} from '../../util/helpers';
import { sortItems, applyFilter } from '../../util/arrays';
import { I18n, i18n } from '../../locale';
import { collate, collateLibrary } from '../../util/format';
import Button from '../../components/Button';
import Loader from '../../components/Loader';
class LibraryArtists extends React.Component {
constructor(props) {
@ -155,12 +156,17 @@ class LibraryArtists extends React.Component {
sort,
sort_reverse,
view,
load_queue,
} = this.props;
const {
limit,
filter,
} = this.state;
if (isLoading(load_queue, ['(.*):library:artists'])) {
return <Loader body loading />;
}
let artists = [
...(source === 'all' || source === 'spotify' ? collate(spotify_library, { items }).items : []),
...(source === 'all' || source === 'google' ? collate(google_library, { items }).items : []),
@ -342,6 +348,7 @@ const mapStateToProps = (state) => ({
sort: (state.ui.library_artists_sort ? state.ui.library_artists_sort : null),
sort_reverse: (state.ui.library_artists_sort_reverse ? state.ui.library_artists_sort_reverse : false),
view: state.ui.library_artists_view,
load_queue: state.ui.load_queue,
});
const mapDispatchToProps = (dispatch) => ({

View File

@ -86,23 +86,31 @@ class LibraryBrowseDirectory extends React.Component {
});
}
playAll(e, tracks) {
const tracks_uris = arrayOf('uri', tracks);
this.props.mopidyActions.playURIs(tracks_uris, `iris:browse:${this.props.uri}`);
this.props.uiActions.hideContextMenu();
playAll = (tracks) => {
const {
uri,
mopidyActions: {
playURIs,
},
uiActions: {
hideContextMenu,
},
} = this.props;
playURIs(arrayOf('uri', tracks), `iris:browse:${uri}`);
hideContextMenu();
}
goBack(e) {
goBack = () => {
const { uiActions: { hideContextMenu } } = this.props;
window.history.back();
this.props.uiActions.hideContextMenu();
hideContextMenu();
}
renderBreadcrumbs() {
if (this.props.uri) {
var parent_uri = this.props.uri;
} else {
return null;
}
renderBreadcrumbs = () => {
const { uri } = this.props;
let parent_uri = uri || null;
if (parent_uri.startsWith('file://')) {
parent_uri = parent_uri.substring(0, parent_uri.lastIndexOf('/'));
@ -120,11 +128,12 @@ class LibraryBrowseDirectory extends React.Component {
return null;
}
renderSubdirectories(subdirectories) {
if (this.props.view === 'list') {
renderSubdirectories = (subdirectories) => {
const { view } = this.props;
if (view === 'list') {
return (
<List
nocontext
rows={subdirectories}
className="library-local-directory-list"
link_prefix="/library/browse/"
@ -219,7 +228,7 @@ class LibraryBrowseDirectory extends React.Component {
/>
{tracks && (
<Button
onClick={(e) => { uiActions.hideContextMenu(); this.playAll(e, all_tracks); }}
onClick={() => { uiActions.hideContextMenu(); this.playAll(all_tracks); }}
noHover
discrete
tracking={{ category: 'Directory', action: 'Play' }}

View File

@ -17,6 +17,8 @@ import * as spotifyActions from '../../services/spotify/actions';
import { applyFilter, removeDuplicates, sortItems } from '../../util/arrays';
import { I18n, i18n } from '../../locale';
import { collate } from '../../util/format';
import { isLoading } from '../../util/helpers';
import Loader from '../../components/Loader';
class LibraryPlaylists extends React.Component {
constructor(props) {
@ -138,12 +140,17 @@ class LibraryPlaylists extends React.Component {
sort_reverse,
view,
source,
load_queue,
} = this.props;
const {
filter,
limit,
} = this.state;
if (isLoading(load_queue, ['(.*):library:playlists'])) {
return <Loader body loading />;
}
let playlists = [
...(source === 'all' || source === 'spotify' ? collate(spotify_library, { items }).items : []),
...(source === 'all' || source === 'local' ? collate(mopidy_library, { items }).items : []),

View File

@ -26,27 +26,29 @@ class EditPlaylist extends React.Component {
}
componentDidMount() {
this.props.uiActions.setWindowTitle(i18n('modal.edit_playlist.title'));
const {
uri,
playlist,
coreActions: {
loadItem,
},
uiActions: {
setWindowTitle,
},
} = this.props;
setWindowTitle(i18n('modal.edit_playlist.title'));
if (this.props.playlist) {
if (playlist) {
this.setState({
loaded: true,
name: this.props.playlist.name,
description: this.props.playlist.description,
public: (this.props.playlist.public == true),
collaborative: (this.props.playlist.collaborative == true),
name: playlist.name,
description: playlist.description,
public: (playlist.public === true),
collaborative: (playlist.collaborative === true),
});
} else {
switch (uriSource(this.props.uri)) {
case 'spotify':
this.props.spotifyActions.getPlaylist(this.props.uri);
this.props.spotifyActions.following(this.props.uri);
break;
default:
this.props.mopidyActions.getPlaylist(this.props.uri);
break;
}
loadItem(uri);
}
}
@ -79,32 +81,13 @@ class EditPlaylist extends React.Component {
return null;
}
savePlaylist(e) {
e.preventDefault();
if (!this.state.name || this.state.name == '') {
this.setState({ error: i18n('modal.edit_playlist.name_required') });
return false;
}
this.props.coreActions.savePlaylist(
this.props.uri,
this.state.name,
this.state.description,
this.state.public,
this.state.collaborative,
this.state.image,
);
window.history.back();
return false;
}
setImage(e) {
setImage = (e) => {
const self = this;
// Create a file-reader to import the selected image as a base64 string
const file_reader = new FileReader();
// Once the image is loaded, convert the result
// Once the image is loaded, convert the result
file_reader.addEventListener('load', (e) => {
const image_base64 = e.target.result.replace('data:image/jpeg;base64,', '');
self.setState({ image: image_base64 });
@ -114,7 +97,51 @@ class EditPlaylist extends React.Component {
file_reader.readAsDataURL(e.target.files[0]);
}
renderFields() {
savePlaylist = (e) => {
const {
name,
description,
public: isPublic,
collaborative,
image,
} = this.state;
const {
uri,
coreActions: {
savePlaylist,
},
} = this.props;
e.preventDefault();
if (!name || name == '') {
this.setState({ error: i18n('modal.edit_playlist.name_required') });
return false;
}
savePlaylist(
uri,
name,
description,
isPublic,
collaborative,
image,
);
window.history.back();
return false;
}
renderFields = () => {
const {
uri,
} = this.props;
const {
name,
description,
public: isPublic,
collaborative,
image,
} = this.state;
switch (uriSource(this.props.uri)) {
case 'spotify':
return (
@ -127,7 +154,7 @@ class EditPlaylist extends React.Component {
<input
type="text"
onChange={(e) => this.setState({ name: e.target.value })}
value={this.state.name}
value={name}
/>
</div>
</div>
@ -139,7 +166,7 @@ class EditPlaylist extends React.Component {
<input
type="text"
onChange={(e) => this.setState({ description: e.target.value })}
value={this.state.description}
value={description}
/>
</div>
</div>
@ -167,8 +194,8 @@ class EditPlaylist extends React.Component {
<input
type="checkbox"
name="playlist_private"
checked={this.state.public}
onChange={(e) => this.setState({ public: !this.state.public })}
checked={isPublic}
onChange={() => this.setState({ public: !isPublic })}
/>
<span className="label">
<I18n path="modal.edit_playlist.options.public" />
@ -178,8 +205,8 @@ class EditPlaylist extends React.Component {
<input
type="checkbox"
name="collaborative"
checked={this.state.collaborative}
onChange={(e) => this.setState({ collaborative: !this.state.collaborative })}
checked={collaborative}
onChange={() => this.setState({ collaborative: !collaborative })}
/>
<span className="label">
<I18n path="modal.edit_playlist.options.collaborative" />
@ -189,7 +216,6 @@ class EditPlaylist extends React.Component {
</div>
</div>
);
break;
default:
return (
@ -202,7 +228,7 @@ class EditPlaylist extends React.Component {
<input
type="text"
onChange={(e) => this.setState({ name: e.target.value })}
value={this.state.name}
value={name}
/>
</div>
</div>
@ -211,13 +237,17 @@ class EditPlaylist extends React.Component {
}
}
render() {
render = () => {
const {
error,
} = this.state;
return (
<Modal className="modal--edit-playlist">
<h1>
<I18n path="modal.edit_playlist.title" />
</h1>
{this.state.error ? <h3 className="red-text">{this.state.error}</h3> : null}
{error ? <h3 className="red-text">{error}</h3> : null}
<form onSubmit={(e) => this.savePlaylist(e)}>
{this.renderFields()}
@ -252,8 +282,7 @@ const mapStateToProps = (state, ownProps) => {
return {
uri,
playlist: (state.core.playlists[uri] !== undefined ? state.core.playlists[uri] : null),
playlists: state.core.playlists,
playlist: (state.core.items[uri] !== undefined ? state.core.items[uri] : null),
};
};