Add/Remove to libraries; Almost ready to bring in to dev pipeline

This commit is contained in:
James Barnsley
2020-09-26 23:03:28 +12:00
parent 3a6d243430
commit 6f6ec6986b
21 changed files with 291 additions and 226 deletions

View File

@ -175,6 +175,22 @@ export function loadLibrary(uri, options = {}) {
};
}
export function addToLibrary(uri, item) {
return {
type: 'ADD_TO_LIBRARY',
uri,
item,
};
}
export function removeFromLibrary(uri, itemUri) {
return {
type: 'REMOVE_FROM_LIBRARY',
uri,
itemUri,
};
}
/**
* Record loaders
@ -265,10 +281,9 @@ export function loadedMore(parent_type, parent_key, records_type, records_data,
};
}
export function removeFromIndex(index_name, key, new_key = null) {
export function removeItem(key, new_key = null) {
return {
type: 'REMOVE_FROM_INDEX',
index_name,
type: 'REMOVE_ITEM',
key,
new_key,
};
@ -349,7 +364,7 @@ export function savePlaylist(uri, name, description = '', is_public = false, is_
export function createPlaylist(scheme, name, description = '', is_public = false, is_collaborative = false) {
switch (scheme) {
case 'spotify':
if (description == '') {
if (description === '') {
description = null;
}
return spotifyActions.createPlaylist(name, description, is_public, is_collaborative);

View File

@ -188,27 +188,6 @@ const CoreMiddleware = (function () {
break;
// Get assets from all of our providers
case 'GET_LIBRARY_PLAYLISTS':
store.dispatch(spotifyActions.getLibraryPlaylists());
store.dispatch(mopidyActions.getLibraryPlaylists());
next(action);
break;
// Get assets from all of our providers
case 'GET_LIBRARY_ALBUMS':
store.dispatch(spotifyActions.getLibraryAlbums());
store.dispatch(mopidyActions.getLibraryAlbums());
next(action);
break;
// Get assets from all of our providers
case 'GET_LIBRARY_ARTISTS':
store.dispatch(spotifyActions.getLibraryArtists());
store.dispatch(mopidyActions.getLibraryArtists());
next(action);
break;
case 'RESTART':
location.reload();
break;
@ -336,7 +315,7 @@ const CoreMiddleware = (function () {
break;
default:
store.dispatch(mopidyActions.getTrack(action.uri));
store.dispatch(mopidyActions.getTrack(action.uri, action.options));
break;
}
};
@ -384,7 +363,7 @@ const CoreMiddleware = (function () {
break;
default:
store.dispatch(mopidyActions.getAlbum(action.uri));
store.dispatch(mopidyActions.getAlbum(action.uri, action.options));
break;
};
};
@ -432,7 +411,7 @@ const CoreMiddleware = (function () {
break;
default:
store.dispatch(mopidyActions.getArtist(action.uri));
store.dispatch(mopidyActions.getArtist(action.uri, action.options));
break;
}
};
@ -498,7 +477,7 @@ const CoreMiddleware = (function () {
break;
default:
store.dispatch(mopidyActions.getPlaylist(action.uri));
store.dispatch(mopidyActions.getPlaylist(action.uri, action.options));
break;
}
};
@ -636,6 +615,39 @@ const CoreMiddleware = (function () {
next(action);
break;
case 'ADD_TO_LIBRARY': {
const library = store.getState().core.libraries[action.uri];
if (library) {
library.items_uris.push(action.item.uri);
store.dispatch(coreActions.libraryLoaded(library));
} else {
// Clear our stored library. This prevents the next call to possibly restore a stale
// library listing.
localForage.removeItem(action.uri);
}
console.log(action);
console.log(library);
store.dispatch(coreActions.itemLoaded({ ...action.item, in_library: true }));
next(action);
break;
}
case 'REMOVE_FROM_LIBRARY': {
const library = store.getState().core.libraries[action.uri];
if (library) {
const items_uris = library.items_uris.filter((uri) => uri !== action.itemUri);
store.dispatch(coreActions.libraryLoaded({
...library,
items_uris,
}));
}
store.dispatch(coreActions.removeItem(action.itemUri));
localForage.removeItem(action.itemUri);
next(action);
break;
}
/**
* Index actions

View File

@ -198,24 +198,17 @@ export default function reducer(core = {}, action) {
* Remove an item from an index
* */
case 'REMOVE_FROM_INDEX':
var index = { ...core[action.index_name] };
case 'REMOVE_ITEM': {
const items = { ...core.items };
// We have a new key to redirect to
if (action.new_key) {
index[action.key] = {
moved_to: action.new_key,
};
// No redirection, so just a clean delete
items[action.key] = { moved_to: action.new_key };
} else {
delete index[action.key];
delete items[action.key];
}
var updated_core = {};
updated_core[action.index_name] = index;
return { ...core, ...updated_core };
return { ...core, items };
}
/**

View File

@ -431,10 +431,11 @@ export function getLibraryPlaylists() {
return { type: 'MOPIDY_GET_LIBRARY_PLAYLISTS' };
}
export function getPlaylist(uri) {
export function getPlaylist(uri, options) {
return {
type: 'MOPIDY_GET_PLAYLIST',
data: { uri },
uri,
options,
};
}
@ -478,10 +479,11 @@ export function clearLibraryArtists() {
};
}
export function getArtist(uri) {
export function getArtist(uri, options) {
return {
type: 'MOPIDY_GET_ARTIST',
uri,
options,
};
}
@ -493,10 +495,11 @@ export function getArtists(uris, processor = null) {
};
}
export function getAlbum(uri) {
export function getAlbum(uri, options) {
return {
type: 'MOPIDY_GET_ALBUM',
uri,
options,
};
}

View File

@ -21,6 +21,7 @@ import {
formatArtists,
formatArtist,
formatPlaylist,
formatPlaylists,
} from '../../util/format';
import {
arrayOf,
@ -1558,7 +1559,7 @@ const MopidyMiddleware = (function () {
case 'MOPIDY_GET_PLAYLIST':
request(store, 'playlists.lookup', action.data)
request(store, 'playlists.lookup', { uri: action.uri })
.then((response) => {
if (!response) return;
@ -1669,7 +1670,7 @@ const MopidyMiddleware = (function () {
if (action.key !== playlist.uri) {
// Remove old playlist (by old key/uri) from index
// By providing the new key, the old playlist gets replaced with a redirector object
store.dispatch(coreActions.removeFromIndex('playlists', action.key, playlist.uri));
store.dispatch(coreActions.removeItem(action.key, playlist.uri));
store.dispatch(coreActions.removePinned(action.key));
store.dispatch(coreActions.addPinned(playlist));
}
@ -1723,24 +1724,20 @@ const MopidyMiddleware = (function () {
case 'MOPIDY_CREATE_PLAYLIST':
request(store, 'playlists.create', { name: action.name, uri_scheme: action.scheme })
.then((response) => {
const playlist = {
...formatPlaylist(response),
...action,
};
store.dispatch(uiActions.createNotification({ content: 'Created playlist' }));
store.dispatch(coreActions.itemLoaded(response));
store.dispatch({
type: 'MOPIDY_LIBRARY_PLAYLIST_CREATED',
key: response.uri,
});
store.dispatch(coreActions.addToLibrary('mopidy:library:playlists', playlist));
});
break;
case 'MOPIDY_DELETE_PLAYLIST':
request(store, 'playlists.delete', { uri: action.uri })
.then((response) => {
.then(() => {
store.dispatch(uiActions.createNotification({ content: 'Deleted playlist' }));
store.dispatch(coreActions.removeFromIndex('playlists', action.uri));
store.dispatch({
type: 'MOPIDY_LIBRARY_PLAYLIST_DELETED',
key: action.uri,
});
store.dispatch(coreActions.removeFromLibrary('mopidy:library:playlists', action.uri));
});
break;

View File

@ -22,6 +22,7 @@ import {
formatTrack,
} from '../../util/format';
import URILink from '../../components/URILink';
import { getItem } from '../../util/selectors';
const coreActions = require('../../services/core/actions');
const uiActions = require('../../services/ui/actions');
@ -737,35 +738,35 @@ export function clearAutocompleteResults(field_id = null) {
export function following(uri, method = 'GET') {
return (dispatch, getState) => {
const asset_name = uriType(uri);
const type = uriType(uri);
let endpoint;
let data;
let is_following = null;
const asset = getState().core[`${asset_name}s`] && getState().core[`${asset_name}s`][uri];
const asset = getItem(getState(), uri) || {};
if (method == 'PUT') {
if (method === 'PUT') {
is_following = true;
} else if (method == 'DELETE') {
} else if (method === 'DELETE') {
is_following = false;
}
switch (asset_name) {
switch (type) {
case 'track':
if (method == 'GET') {
if (method === 'GET') {
endpoint = `me/tracks/contains?ids=${getFromUri('trackid', uri)}`;
} else {
endpoint = `me/tracks?ids=${getFromUri('trackid', uri)}`;
}
break;
case 'album':
if (method == 'GET') {
if (method === 'GET') {
endpoint = `me/albums/contains?ids=${getFromUri('albumid', uri)}`;
} else {
endpoint = `me/albums?ids=${getFromUri('albumid', uri)}`;
}
break;
case 'artist':
if (method == 'GET') {
if (method === 'GET') {
endpoint = `me/following/contains?type=artist&ids=${getFromUri('artistid', uri)}`;
} else {
endpoint = `me/following?type=artist&ids=${getFromUri('artistid', uri)}`;
@ -773,7 +774,7 @@ export function following(uri, method = 'GET') {
}
break;
case 'user':
if (method == 'GET') {
if (method === 'GET') {
endpoint = `me/following/contains?type=user&ids=${getFromUri('userid', uri)}`;
} else {
endpoint = `me/following?type=user&ids=${getFromUri('userid', uri)}`;
@ -781,7 +782,7 @@ export function following(uri, method = 'GET') {
}
break;
case 'playlist':
if (method == 'GET') {
if (method === 'GET') {
endpoint = `playlists/${getFromUri('playlistid', uri)}/followers/contains?ids=${getState().spotify.me.id}`;
} else {
endpoint = `playlists/${getFromUri('playlistid', uri)}/followers?`;
@ -795,23 +796,20 @@ export function following(uri, method = 'GET') {
.then(
(response) => {
if (Array.isArray(response) && response.length > 0) {
is_following = response[0];
asset.in_library = response[0];
} else {
is_following = is_following;
asset.in_library = is_following;
}
dispatch(coreActions.itemLoaded({
uri,
in_library: is_following,
}));
if (method === 'DELETE') {
dispatch(coreActions.removeFromLibrary(`spotify:library:${type}s`, uri));
dispatch(uiActions.createNotification({
content: <span>Removed <URILink uri={uri}>{asset ? asset.name : asset_name}</URILink> from library</span>,
content: <span>Removed <URILink uri={uri}>{asset ? asset.name : type}</URILink> from library</span>,
}));
} else if (method === 'PUT' || method === 'POST') {
dispatch(coreActions.addToLibrary(`spotify:library:${type}s`, asset));
dispatch(uiActions.createNotification({
content: <span>Added <URILink uri={uri}>{asset ? asset.name : asset_name}</URILink> to library</span>,
content: <span>Added <URILink uri={uri}>{asset ? asset.name : type}</URILink> to library</span>,
}));
}
},