Search fully functional; Loading images properly, and dependent URIs

This commit is contained in:
James Barnsley
2020-10-14 21:19:21 +13:00
parent 73d24270a8
commit fdcd15fbd3
10 changed files with 374 additions and 442 deletions

View File

@ -103765,6 +103765,20 @@ var DebugInfo = /*#__PURE__*/function (_React$Component) {
_defineProperty(_assertThisInitialized(_this), "render", function () {
var localStorageUsage = _this.localStorageSize();
var _this$props = _this.props,
_this$props$core$item = _this$props.core.items,
items = _this$props$core$item === void 0 ? {} : _this$props$core$item,
_this$props$ui = _this$props.ui,
_this$props$ui$notifi = _this$props$ui.notifications,
notifications = _this$props$ui$notifi === void 0 ? {} : _this$props$ui$notifi,
_this$props$ui$proces = _this$props$ui.processes,
processes = _this$props$ui$proces === void 0 ? {} : _this$props$ui$proces,
slim_mode = _this$props$ui.slim_mode,
test_mode = _this$props$ui.test_mode,
_this$props$ui$select = _this$props$ui.selected_tracks,
selected_tracks = _this$props$ui$select === void 0 ? [] : _this$props$ui$select,
_this$props$mopidy$en = _this$props.mopidy.enqueue_uris_batches,
enqueue_uris_batches = _this$props$mopidy$en === void 0 ? [] : _this$props$mopidy$en;
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info",
"data-qa-node": "div",
@ -103792,47 +103806,27 @@ var DebugInfo = /*#__PURE__*/function (_React$Component) {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Items:", ' ', _this.props.core.items ? Object.keys(_this.props.core.items).length : '0'), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
}, "Items: ".concat(Object.keys(items).length)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Coldstore items:", ' ', _this.state.localForageLength), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
}, "Coldstore items: ".concat(_this.state.localForageLength)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Albums:", ' ', _this.props.core.albums ? Object.keys(_this.props.core.albums).length : '0'), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
}, "Notifications: ".concat(Object.keys(notifications).length)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Artists:", ' ', _this.props.core.artists ? Object.keys(_this.props.core.artists).length : '0'), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
}, "Processes: ".concat(Object.keys(processes).length)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Playlists:", ' ', _this.props.core.playlists ? Object.keys(_this.props.core.playlists).length : '0'), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
}, "Enqueue batches: ".concat(enqueue_uris_batches.length)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Tracks:", ' ', _this.props.core.tracks ? Object.keys(_this.props.core.tracks).length : '0'), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Users:", ' ', _this.props.core.users ? Object.keys(_this.props.core.users).length : '0'), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Notifications:", ' ', _this.props.ui.notifications ? Object.keys(_this.props.ui.notifications).length : '0'), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Processes:", ' ', _this.props.ui.processes ? Object.keys(_this.props.ui.processes).length : '0'), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Enqueue batches:", ' ', _this.props.mopidy.enqueue_uris_batches ? _this.props.mopidy.enqueue_uris_batches.length : '0'), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Cached URLs:", ' ', Object.keys(Object(_util_storage__WEBPACK_IMPORTED_MODULE_3__["get"])('cache')).length)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
}, "Cached URLs: ".concat(Object.keys(Object(_util_storage__WEBPACK_IMPORTED_MODULE_3__["get"])('cache')).length))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-section",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
@ -103843,26 +103837,26 @@ var DebugInfo = /*#__PURE__*/function (_React$Component) {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Slim mode:", ' ', _this.props.ui.slim_mode ? 'on' : 'off'), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
}, "Slim mode: ".concat(slim_mode ? 'on' : 'off')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Test mode:", ' ', _this.props.ui.test_mode ? 'on' : 'off'), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
}, "Test mode: ".concat(test_mode ? 'on' : 'off')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Touch:", ' ', Object(_util_helpers__WEBPACK_IMPORTED_MODULE_4__["isTouchDevice"])() ? 'on' : 'off'), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
}, "Touch: ".concat(Object(_util_helpers__WEBPACK_IMPORTED_MODULE_4__["isTouchDevice"])() ? 'on' : 'off')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "LocalStorage usage:", ' ', localStorageUsage.used, "kb (~", localStorageUsage.percent, "%)"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
}, "LocalStorage usage: ".concat(localStorageUsage.used, "kb (~").concat(localStorageUsage.percent, "%)")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
className: "debug-info-item",
"data-qa-node": "div",
"data-qa-file": "DebugInfo"
}, "Selected tracks:", ' ', _this.props.ui.selected_tracks.length, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("br", {
}, "Selected tracks: ".concat(selected_tracks.length), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("br", {
"data-qa-node": "br",
"data-qa-file": "DebugInfo"
}), _this.props.ui.selected_tracks.map(function (track_key, index) {
}), selected_tracks.map(function (track_key, index) {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
key: "".concat(track_key, "_").concat(index),
"data-qa-node": "div",
@ -117784,7 +117778,7 @@ var ensureLoaded = function ensureLoaded(_ref) {
var getDependentUris = function getDependentUris(parent) {
if (!parent) return [];
return [].concat(_toConsumableArray(dependents), _toConsumableArray(fullDependents)).reduce(function (acc, dependent) {
return [].concat(_toConsumableArray(acc), _toConsumableArray(dependent.match(new RegExp('/(.*)_uri(.*)')) ? parent[dependent] : []));
return [].concat(_toConsumableArray(acc), _toConsumableArray(dependent.match(new RegExp('(.*)_uri(.*)')) ? parent[dependent] : []));
}, []);
}; // Forced refetch bypasses everything
@ -117800,9 +117794,7 @@ var ensureLoaded = function ensureLoaded(_ref) {
if (getMissingDependents(item).length === 0) {
console.info("\"".concat(uri, "\" and all dependents already in index"));
store.dispatch(uiActions.stopLoading(uri));
getDependentUris(item).forEach(function (dependent) {
return store.dispatch(coreActions.loadItems(item[dependent]));
});
coreActions.loadItems(getDependentUris(item));
return;
}
} // What about in the coldstore?
@ -118071,15 +118063,8 @@ var CoreMiddleware = function () {
term: term,
type: type
}
}, term === prevTerm && type === prevType ? allResults : {});
}, term === prevTerm && type === prevType ? allResults : {}); // Merge our new results with the existing (if any)
console.log({
term: term,
type: type,
prevTerm: prevTerm,
prevType: prevType,
allResults: allResults
}); // Merge our new results with the existing (if any)
search_results[resultType] = [].concat(_toConsumableArray(search_results[resultType] || []), _toConsumableArray(results));
next(_objectSpread(_objectSpread({}, action), {}, {
@ -118092,115 +118077,93 @@ var CoreMiddleware = function () {
location.reload();
break;
/**
* Playlist manipulation
* */
case 'PLAYLIST_TRACKS':
var playlist_tracks = Object(_util_format__WEBPACK_IMPORTED_MODULE_7__["formatTracks"])(action.tracks);
store.dispatch({
type: 'TRACKS_LOADED',
tracks: playlist_tracks
});
next(_objectSpread(_objectSpread({}, action), {}, {
tracks_uris: Object(_util_arrays__WEBPACK_IMPORTED_MODULE_4__["arrayOf"])('uri', playlist_tracks)
}));
break;
case 'PLAYLIST_TRACKS_ADDED':
var asset = store.getState().core.playlists[action.key];
store.dispatch(uiActions.createNotification({
content: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("span", {
"data-qa-node": "span",
"data-qa-file": "middleware"
}, "Added ", action.tracks_uris.length, " tracks to ", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_URILink__WEBPACK_IMPORTED_MODULE_5__["default"], {
uri: action.key,
"data-qa-node": "URILink",
"data-qa-file": "middleware"
}, asset ? asset.name : 'playlist'))
}));
{
var key = action.key,
tracks_uris = action.tracks_uris;
switch (Object(_util_helpers__WEBPACK_IMPORTED_MODULE_6__["uriSource"])(action.key)) {
case 'spotify':
store.dispatch(spotifyActions.getPlaylist(action.key));
break;
var _store$getState5 = store.getState(),
asset = _store$getState5.core.items[key];
case 'm3u':
store.dispatch(mopidyActions.getPlaylist(action.key));
break;
store.dispatch(uiActions.createNotification({
content: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("span", {
"data-qa-node": "span",
"data-qa-file": "middleware"
}, "Added ", tracks_uris.length, " tracks to ", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_URILink__WEBPACK_IMPORTED_MODULE_5__["default"], {
uri: key,
"data-qa-node": "URILink",
"data-qa-file": "middleware"
}, asset ? asset.name : 'playlist'))
}));
default:
break;
switch (Object(_util_helpers__WEBPACK_IMPORTED_MODULE_6__["uriSource"])(key)) {
case 'spotify':
store.dispatch(spotifyActions.getPlaylist(key));
break;
case 'm3u':
store.dispatch(mopidyActions.getPlaylist(key));
break;
default:
break;
}
next(action);
break;
}
next(action);
break;
case 'PLAYLIST_TRACKS_REORDERED':
var playlists = _objectSpread({}, core.playlists);
{
var _key = action.key,
snapshot_id = action.snapshot_id;
var insert_before = action.insert_before;
var playlist = _objectSpread({}, playlists[action.key]);
var playlist = _objectSpread({}, core.items[_key]);
var tracks_uris = Object.assign([], playlist.tracks_uris); // handle insert_before offset if we're moving BENEATH where we're slicing tracks
var tracks = Object.assign([], playlist.tracks); // handle insert_before offset if we're moving BENEATH where we're slicing tracks
var insert_before = action.insert_before;
if (insert_before > action.range_start) {
insert_before -= action.range_length;
} // cut our moved tracks into a new array
if (insert_before > action.range_start) {
insert_before -= action.range_length;
} // cut our moved tracks into a new array
var tracks_to_move = tracks_uris.splice(action.range_start, action.range_length);
tracks_to_move.reverse();
var tracks_to_move = tracks.splice(action.range_start, action.range_length);
tracks_to_move.reverse();
for (i = 0; i < tracks_to_move.length; i++) {
tracks_uris.splice(insert_before, 0, tracks_to_move[i]);
for (var i = 0; i < tracks_to_move.length; i++) {
tracks.splice(insert_before, 0, tracks_to_move[i]);
}
store.dispatch(coreActions.itemLoaded(_objectSpread(_objectSpread({}, playlist), {}, {
tracks: tracks,
snapshot_id: snapshot_id
})));
break;
}
var snapshot_id = null;
if (action.snapshot_id) {
snapshot_id = action.snapshot_id;
} // Update our playlist
playlist.tracks_uris = tracks_uris;
playlist.snapshot_id = snapshot_id; // Trigger normal playlist updating
store.dispatch({
type: 'PLAYLISTS_LOADED',
playlists: [playlist]
});
break;
case 'PLAYLIST_TRACKS_REMOVED':
var playlists = _objectSpread({}, core.playlists);
{
var _key2 = action.key,
_snapshot_id = action.snapshot_id;
var playlist = _objectSpread({}, playlists[action.key]);
var _playlist = _objectSpread({}, core.items[_key2]);
var tracks_uris = Object.assign([], playlist.tracks_uris);
var indexes = action.tracks_indexes.reverse();
var _tracks = Object.assign([], _playlist.tracks);
for (var i = 0; i < indexes.length; i++) {
tracks_uris.splice(indexes[i], 1);
var indexes = action.tracks_indexes.reverse();
for (var _i = 0; _i < indexes.length; _i++) {
_tracks.splice(indexes[_i], 1);
}
store.dispatch(coreActions.itemLoaded(_objectSpread(_objectSpread({}, _playlist), {}, {
tracks: _tracks,
snapshot_id: _snapshot_id
})));
break;
}
var snapshot_id = null;
if (action.snapshot_id) {
snapshot_id = action.snapshot_id;
} // Update our playlist
playlist.tracks_uris = tracks_uris;
playlist.snapshot_id = snapshot_id; // Trigger normal playlist updating
store.dispatch({
type: 'PLAYLISTS_LOADED',
playlists: [playlist]
});
break;
/**
* Asset Load commands
*
@ -122066,38 +122029,34 @@ var MopidyMiddleware = function () {
type: query.type,
term: query.term,
requestType: type,
uri_scheme: uri_scheme
uri_scheme: uri_scheme,
data: {
uris: [uri_scheme]
}
};
switch (type) {
case 'tracks':
item.data = {
query: {
track_name: [query.term]
},
uris: [uri_scheme]
item.data.query = {
any: [query.term]
};
break;
case 'artists':
item.data = {
query: {
artist: [query.term]
},
uris: [uri_scheme]
item.data.query = {
artist: [query.term]
};
break;
case 'albums':
item.data = {
query: {
album: [query.term]
},
uris: [uri_scheme]
item.data.query = {
album: [query.term]
};
break;
case 'playlists':
// Searching for playlists is not supported, so we get a simple
// list of names and perform a client-side regex match
item.method = 'playlists.asList';
item.data = {};
break;
@ -122438,23 +122397,24 @@ var MopidyMiddleware = function () {
break;
case 'MOPIDY_CURRENT_TRACK_LOADED':
// Let the UI know we're finished transition
store.dispatch(uiActions.setCurrentTrackTransition(false));
var track = Object(_util_format__WEBPACK_IMPORTED_MODULE_6__["formatTrack"])(action.tl_track);
{
store.dispatch(uiActions.setCurrentTrackTransition(false));
var track = Object(_util_format__WEBPACK_IMPORTED_MODULE_6__["formatTrack"])(action.tl_track);
if (track.uri) {
store.dispatch({
type: 'CURRENT_TRACK_LOADED',
track: track,
uri: track.uri
});
store.dispatch(coreActions.loadItem(track.uri, {
full: true
}));
if (track.uri) {
store.dispatch({
type: 'CURRENT_TRACK_LOADED',
track: track,
uri: track.uri
});
store.dispatch(coreActions.loadItem(track.uri, {
full: true
}));
}
break;
}
break;
case 'MOPIDY_GET_NEXT_TRACK':
request(store, 'tracklist.getNextTlid').then(function (response) {
if (response && response >= 0) {
@ -122480,8 +122440,10 @@ var MopidyMiddleware = function () {
uris: action.uris
}).then(function (_response) {
if (!_response) return;
var tracks = Object(_util_arrays__WEBPACK_IMPORTED_MODULE_7__["indexToArray"])(_response);
store.dispatch(coreActions.itemsLoaded(Object(_util_format__WEBPACK_IMPORTED_MODULE_6__["formatTracks"])(tracks)));
var tracks = Object(lodash__WEBPACK_IMPORTED_MODULE_3__["compact"])(Object(_util_arrays__WEBPACK_IMPORTED_MODULE_7__["indexToArray"])(_response).map(function (results) {
return results.length ? Object(_util_format__WEBPACK_IMPORTED_MODULE_6__["formatTrack"])(results[0]) : null;
}));
store.dispatch(coreActions.itemsLoaded(tracks));
if (action.get_images) {
store.dispatch(mopidyActions.getImages(Object(_util_arrays__WEBPACK_IMPORTED_MODULE_7__["arrayOf"])('uri', tracks)));
@ -122513,41 +122475,40 @@ var MopidyMiddleware = function () {
});
break;
/**
* =============================================================== IMAGES ===============
* ======================================================================================
* */
case 'MOPIDY_GET_IMAGES':
if (action.uris) {
request(store, 'library.getImages', {
uris: action.uris
}).then(function (response) {
var itemsWithImages = [];
Object.keys(response).forEach(function (uri) {
var images = response[uri];
{
var _uris = action.uris;
if (images) {
itemsWithImages.push({
uri: uri,
images: Object(_util_format__WEBPACK_IMPORTED_MODULE_6__["formatImages"])(Object(_util_format__WEBPACK_IMPORTED_MODULE_6__["digestMopidyImages"])(store.getState().mopidy, images))
});
} else {
store.dispatch(lastfmActions.getImages(uri));
if (action.uris) {
request(store, 'library.getImages', {
uris: _uris
}).then(function (response) {
var itemsWithImages = [];
Object.keys(response).forEach(function (uri) {
var images = response[uri];
if (images) {
itemsWithImages.push({
uri: uri,
images: Object(_util_format__WEBPACK_IMPORTED_MODULE_6__["formatImages"])(Object(_util_format__WEBPACK_IMPORTED_MODULE_6__["digestMopidyImages"])(store.getState().mopidy, images))
});
} else {
store.dispatch(lastfmActions.getImages(uri));
}
;
});
if (itemsWithImages.length) {
store.dispatch(coreActions.itemsLoaded(itemsWithImages));
}
;
});
}
if (itemsWithImages.length) {
store.dispatch(coreActions.itemsLoaded(itemsWithImages));
}
});
next(action);
break;
}
next(action);
break;
/**
* =============================================================== LOCAL ================
* ======================================================================================
@ -126771,10 +126732,13 @@ var SpotifyMiddleware = function () {
break;
case 'SPOTIFY_REMOVE_PLAYLIST_TRACKS':
var playlist = _objectSpread({}, store.getState().core.playlists[action.key]);
{
var _ref = store.getState().core.items[action.key] || {},
snapshot_id = _ref.snapshot_id;
store.dispatch(spotifyActions.deleteTracksFromPlaylist(playlist.uri, playlist.snapshot_id, action.tracks_indexes));
break;
store.dispatch(spotifyActions.deleteTracksFromPlaylist(action.key, snapshot_id, action.tracks_indexes));
break;
}
case 'SPOTIFY_ADD_PLAYLIST_TRACKS':
store.dispatch(spotifyActions.addTracksToPlaylist(action.key, action.tracks_uris));
@ -136892,7 +136856,7 @@ var Search = /*#__PURE__*/function (_React$Component) {
});
_defineProperty(_assertThisInitialized(_this), "onSourceClose", function () {
_this.search();
_this.search(true);
});
_defineProperty(_assertThisInitialized(_this), "digestUri", function () {
@ -136922,37 +136886,28 @@ var Search = /*#__PURE__*/function (_React$Component) {
});
_defineProperty(_assertThisInitialized(_this), "search", function () {
var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var _this$props3 = _this.props,
startSearch = _this$props3.coreActions.startSearch,
setWindowTitle = _this$props3.uiActions.setWindowTitle;
setWindowTitle = _this$props3.uiActions.setWindowTitle,
_this$props3$search_r = _this$props3.search_results_query,
existingType = _this$props3$search_r.type,
existingTerm = _this$props3$search_r.term;
var _this$state2 = _this.state,
type = _this$state2.type,
term = _this$state2.term;
setWindowTitle(Object(_locale__WEBPACK_IMPORTED_MODULE_20__["i18n"])('search.title_window', {
term: decodeURIComponent(term)
}));
/**
* TODO: Searches are being triggered when navigating to type subviews, despite already having
* results. This might be a consequence of having providers merging their results into one array
*/
if (type && term) {
if (type && term && (force || existingType !== type || existingTerm !== term)) {
startSearch({
type: type,
term: term
});
/*
mopidyActions.getSearchResults(type, term);
if (uri_schemes_search_enabled.includes('spotify:')) {
spotifyActions.getSearchResults(type, term);
}*/
}
});
_defineProperty(_assertThisInitialized(_this), "loadMore", function (type) {
alert("load more: ".concat(type)); // this.props.spotifyActions.getURL(this.props['spotify_'+type+'_more'], 'SPOTIFY_SEARCH_RESULTS_LOADED_MORE_'+type.toUpperCase());
});
_defineProperty(_assertThisInitialized(_this), "setSort", function (value) {
var _this$props4 = _this.props,
sort = _this$props4.sort,
@ -137182,13 +137137,29 @@ var Search = /*#__PURE__*/function (_React$Component) {
}(react__WEBPACK_IMPORTED_MODULE_0___default.a.Component);
var mapStateToProps = function mapStateToProps(state, ownProps) {
var _ownProps$match$param = ownProps.match.params,
type = _ownProps$match$param.type,
term = _ownProps$match$param.term;
var _state$mopidy$uri_sch = state.mopidy.uri_schemes,
uri_schemes = _state$mopidy$uri_sch === void 0 ? [] : _state$mopidy$uri_sch,
_state$ui = state.ui,
_state$ui$uri_schemes = _state$ui.uri_schemes_search_enabled,
uri_schemes_search_enabled = _state$ui$uri_schemes === void 0 ? [] : _state$ui$uri_schemes,
_state$ui$search_resu = _state$ui.search_results_sort,
sort = _state$ui$search_resu === void 0 ? 'followers.total' : _state$ui$search_resu,
search_results_sort_reverse = _state$ui.search_results_sort_reverse,
_state$core$search_re = state.core.search_results;
_state$core$search_re = _state$core$search_re === void 0 ? {} : _state$core$search_re;
var _state$core$search_re2 = _state$core$search_re.query,
search_results_query = _state$core$search_re2 === void 0 ? {} : _state$core$search_re2;
return {
type: ownProps.match.params.type,
term: ownProps.match.params.term,
uri_schemes_search_enabled: state.ui.uri_schemes_search_enabled || [],
uri_schemes: state.mopidy.uri_schemes || [],
sort: state.ui.search_results_sort || 'followers.total',
sort_reverse: !!state.ui.search_results_sort_reverse
type: type,
term: term,
uri_schemes: uri_schemes,
uri_schemes_search_enabled: uri_schemes_search_enabled,
sort: sort,
sort_reverse: !!search_results_sort_reverse,
search_results_query: search_results_query
};
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -106,7 +106,7 @@
// Release details
// These are automatically injected to built HTML
var build = "1602614727";
var build = "1602663216";
var version = "3.53.0";
// Construct the script tag

View File

@ -55,6 +55,21 @@ class DebugInfo extends React.Component {
render = () => {
const localStorageUsage = this.localStorageSize();
const {
core: {
items = {},
},
ui: {
notifications = {},
processes = {},
slim_mode,
test_mode,
selected_tracks = [],
},
mopidy: {
enqueue_uris_batches = [],
},
} = this.props;
return (
<div className="debug-info">
@ -75,95 +90,45 @@ class DebugInfo extends React.Component {
<div className="debug-info-section">
<h5>State</h5>
<div className="debug-info-item">
Items:
{' '}
{this.props.core.items ? Object.keys(this.props.core.items).length : '0'}
{`Items: ${Object.keys(items).length}`}
</div>
<div className="debug-info-item">
Coldstore items:
{' '}
{this.state.localForageLength}
{`Coldstore items: ${this.state.localForageLength}`}
</div>
<div className="debug-info-item">
Albums:
{' '}
{this.props.core.albums ? Object.keys(this.props.core.albums).length : '0'}
{`Notifications: ${Object.keys(notifications).length}`}
</div>
<div className="debug-info-item">
Artists:
{' '}
{this.props.core.artists ? Object.keys(this.props.core.artists).length : '0'}
{`Processes: ${Object.keys(processes).length}`}
</div>
<div className="debug-info-item">
Playlists:
{' '}
{this.props.core.playlists ? Object.keys(this.props.core.playlists).length : '0'}
{`Enqueue batches: ${enqueue_uris_batches.length}`}
</div>
<div className="debug-info-item">
Tracks:
{' '}
{this.props.core.tracks ? Object.keys(this.props.core.tracks).length : '0'}
</div>
<div className="debug-info-item">
Users:
{' '}
{this.props.core.users ? Object.keys(this.props.core.users).length : '0'}
</div>
<div className="debug-info-item">
Notifications:
{' '}
{this.props.ui.notifications ? Object.keys(this.props.ui.notifications).length : '0'}
</div>
<div className="debug-info-item">
Processes:
{' '}
{this.props.ui.processes ? Object.keys(this.props.ui.processes).length : '0'}
</div>
<div className="debug-info-item">
Enqueue batches:
{' '}
{this.props.mopidy.enqueue_uris_batches ? this.props.mopidy.enqueue_uris_batches.length : '0'}
</div>
<div className="debug-info-item">
Cached URLs:
{' '}
{Object.keys(getStorage('cache')).length}
{`Cached URLs: ${Object.keys(getStorage('cache')).length}`}
</div>
</div>
<div className="debug-info-section">
<h5>Config</h5>
<div className="debug-info-item">
Slim mode:
{' '}
{this.props.ui.slim_mode ? 'on' : 'off'}
{`Slim mode: ${slim_mode ? 'on' : 'off'}`}
</div>
<div className="debug-info-item">
Test mode:
{' '}
{this.props.ui.test_mode ? 'on' : 'off'}
{`Test mode: ${test_mode ? 'on' : 'off'}`}
</div>
<div className="debug-info-item">
Touch:
{' '}
{isTouchDevice() ? 'on' : 'off'}
{`Touch: ${isTouchDevice() ? 'on' : 'off'}`}
</div>
<div className="debug-info-item">
LocalStorage usage:
{' '}
{localStorageUsage.used}
kb (~
{localStorageUsage.percent}
%)
{`LocalStorage usage: ${localStorageUsage.used}kb (~${localStorageUsage.percent}%)`}
</div>
<div className="debug-info-item">
Selected tracks:
{' '}
{this.props.ui.selected_tracks.length}
{`Selected tracks: ${selected_tracks.length}`}
<br />
{
this.props.ui.selected_tracks.map((track_key, index) => (
<div key={`${track_key}_${index}`}>{track_key}</div>
selected_tracks.map((track_key, index) => (
<div key={`${track_key}_${index}`}>{track_key}</div>
))
}
</div>

View File

@ -9,11 +9,6 @@ import {
formatTracks,
formatTrack,
formatSimpleObject,
formatAlbum,
formatArtist,
formatPlaylist,
formatUser,
formatSimpleObjects,
} from '../../util/format';
import { handleException } from './actions';
@ -66,10 +61,12 @@ const ensureLoaded = ({
if (!parent) return [];
return [...dependents, ...fullDependents].reduce(
(acc, dependent) => [
...acc,
...(dependent.match(new RegExp('/(.*)_uri(.*)')) ? parent[dependent] : []),
],
(acc, dependent) => {
return [
...acc,
...(dependent.match(new RegExp('(.*)_uri(.*)')) ? parent[dependent] : []),
];
},
[],
);
};
@ -86,10 +83,7 @@ const ensureLoaded = ({
if (getMissingDependents(item).length === 0) {
console.info(`"${uri}" and all dependents already in index`);
store.dispatch(uiActions.stopLoading(uri));
getDependentUris(item).forEach(
(dependent) => store.dispatch(coreActions.loadItems(item[dependent])),
);
coreActions.loadItems(getDependentUris(item));
return;
}
}
@ -327,14 +321,6 @@ const CoreMiddleware = (function () {
...(term === prevTerm && type === prevType ? allResults : {}),
};
console.log({
term,
type,
prevTerm,
prevType,
allResults,
});
// Merge our new results with the existing (if any)
search_results[resultType] = [
...(search_results[resultType] || []),
@ -352,98 +338,89 @@ const CoreMiddleware = (function () {
location.reload();
break;
/**
* Playlist manipulation
* */
case 'PLAYLIST_TRACKS':
const playlist_tracks = formatTracks(action.tracks);
store.dispatch({
type: 'TRACKS_LOADED',
tracks: playlist_tracks,
});
next({ ...action, tracks_uris: arrayOf('uri', playlist_tracks) });
break;
case 'PLAYLIST_TRACKS_ADDED':
const asset = store.getState().core.playlists[action.key];
case 'PLAYLIST_TRACKS_ADDED': {
const {
key,
tracks_uris,
} = action;
const {
core: {
items: {
[key]: asset,
},
},
} = store.getState();
store.dispatch(uiActions.createNotification({
content: <span>Added {action.tracks_uris.length} tracks to <URILink uri={action.key}>{asset ? asset.name : 'playlist'}</URILink></span>,
content: (
<span>
Added {tracks_uris.length} tracks to <URILink uri={key}>{asset ? asset.name : 'playlist'}</URILink>
</span>
),
}));
switch (uriSource(action.key)) {
switch (uriSource(key)) {
case 'spotify':
store.dispatch(spotifyActions.getPlaylist(action.key));
store.dispatch(spotifyActions.getPlaylist(key));
break;
case 'm3u':
store.dispatch(mopidyActions.getPlaylist(action.key));
store.dispatch(mopidyActions.getPlaylist(key));
break;
default:
break;
}
next(action);
break;
}
case 'PLAYLIST_TRACKS_REORDERED':
var playlists = { ...core.playlists };
var playlist = { ...playlists[action.key] };
var tracks_uris = Object.assign([], playlist.tracks_uris);
case 'PLAYLIST_TRACKS_REORDERED': {
const {
key,
snapshot_id,
} = action;
let { insert_before } = action;
const playlist = { ...core.items[key] };
const tracks = Object.assign([], playlist.tracks);
// handle insert_before offset if we're moving BENEATH where we're slicing tracks
var { insert_before } = action;
if (insert_before > action.range_start) {
insert_before -= action.range_length;
}
// cut our moved tracks into a new array
var tracks_to_move = tracks_uris.splice(action.range_start, action.range_length);
const tracks_to_move = tracks.splice(action.range_start, action.range_length);
tracks_to_move.reverse();
for (i = 0; i < tracks_to_move.length; i++) {
tracks_uris.splice(insert_before, 0, tracks_to_move[i]);
for (let i = 0; i < tracks_to_move.length; i++) {
tracks.splice(insert_before, 0, tracks_to_move[i]);
}
var snapshot_id = null;
if (action.snapshot_id) {
snapshot_id = action.snapshot_id;
}
// Update our playlist
playlist.tracks_uris = tracks_uris;
playlist.snapshot_id = snapshot_id;
// Trigger normal playlist updating
store.dispatch({
type: 'PLAYLISTS_LOADED',
playlists: [playlist],
});
store.dispatch(coreActions.itemLoaded({
...playlist,
tracks,
snapshot_id,
}));
break;
}
case 'PLAYLIST_TRACKS_REMOVED':
var playlists = { ...core.playlists };
var playlist = { ...playlists[action.key] };
var tracks_uris = Object.assign([], playlist.tracks_uris);
var indexes = action.tracks_indexes.reverse();
for (var i = 0; i < indexes.length; i++) {
tracks_uris.splice(indexes[i], 1);
case 'PLAYLIST_TRACKS_REMOVED': {
const {
key,
snapshot_id,
} = action;
const playlist = { ...core.items[key] };
const tracks = Object.assign([], playlist.tracks);
const indexes = action.tracks_indexes.reverse();
for (let i = 0; i < indexes.length; i++) {
tracks.splice(indexes[i], 1);
}
var snapshot_id = null;
if (action.snapshot_id) {
snapshot_id = action.snapshot_id;
}
// Update our playlist
playlist.tracks_uris = tracks_uris;
playlist.snapshot_id = snapshot_id;
// Trigger normal playlist updating
store.dispatch({
type: 'PLAYLISTS_LOADED',
playlists: [playlist],
});
store.dispatch(coreActions.itemLoaded({
...playlist,
tracks,
snapshot_id,
}));
break;
}
/**
* Asset Load commands

View File

@ -2,7 +2,7 @@
import ReactGA from 'react-ga';
import Mopidy from 'mopidy';
import { sha256 } from 'js-sha256';
import { sampleSize, uniqBy } from 'lodash';
import { sampleSize, compact } from 'lodash';
import { i18n } from '../../locale';
import {
generateGuid,
@ -1147,18 +1147,23 @@ const MopidyMiddleware = (function () {
term: query.term,
requestType: type,
uri_scheme,
data: {
uris: [uri_scheme],
},
};
switch (type) {
case 'tracks':
item.data = { query: { track_name: [query.term] }, uris: [uri_scheme] };
item.data.query = { any: [query.term] };
break;
case 'artists':
item.data = { query: { artist: [query.term] }, uris: [uri_scheme] };
item.data.query = { artist: [query.term] };
break;
case 'albums':
item.data = { query: { album: [query.term] }, uris: [uri_scheme] };
item.data.query = { album: [query.term] };
break;
case 'playlists':
// Searching for playlists is not supported, so we get a simple
// list of names and perform a client-side regex match
item.method = 'playlists.asList';
item.data = {};
break;
@ -1489,22 +1494,19 @@ const MopidyMiddleware = (function () {
);
break;
case 'MOPIDY_CURRENT_TRACK_LOADED':
// Let the UI know we're finished transition
case 'MOPIDY_CURRENT_TRACK_LOADED': {
store.dispatch(uiActions.setCurrentTrackTransition(false));
var track = formatTrack(action.tl_track);
const track = formatTrack(action.tl_track);
if (track.uri) {
store.dispatch({
type: 'CURRENT_TRACK_LOADED',
track,
uri: track.uri,
});
store.dispatch(coreActions.loadItem(track.uri, { full: true }));
}
break;
}
case 'MOPIDY_GET_NEXT_TRACK':
request(store, 'tracklist.getNextTlid')
@ -1539,10 +1541,11 @@ const MopidyMiddleware = (function () {
.then(
(_response) => {
if (!_response) return;
const tracks = compact(indexToArray(_response).map(
(results) => (results.length ? formatTrack(results[0]) : null),
));
const tracks = indexToArray(_response);
store.dispatch(coreActions.itemsLoaded(formatTracks(tracks)));
store.dispatch(coreActions.itemsLoaded(tracks));
if (action.get_images) {
store.dispatch(mopidyActions.getImages(arrayOf('uri', tracks)));
@ -1588,15 +1591,10 @@ const MopidyMiddleware = (function () {
);
break;
/**
* =============================================================== IMAGES ===============
* ======================================================================================
* */
case 'MOPIDY_GET_IMAGES':
case 'MOPIDY_GET_IMAGES': {
const { uris } = action;
if (action.uris) {
request(store, 'library.getImages', { uris: action.uris })
request(store, 'library.getImages', { uris })
.then((response) => {
const itemsWithImages = [];
Object.keys(response).forEach((uri) => {
@ -1620,6 +1618,7 @@ const MopidyMiddleware = (function () {
next(action);
break;
}
/**

View File

@ -1509,23 +1509,28 @@ export function addTracksToPlaylist(uri, tracks_uris) {
export function deleteTracksFromPlaylist(uri, snapshot_id, tracks_indexes) {
return (dispatch, getState) => {
request(dispatch, getState, `playlists/${getFromUri('playlistid', uri)}/tracks`, 'DELETE', { snapshot_id, positions: tracks_indexes })
.then(
(response) => {
dispatch({
type: 'PLAYLIST_TRACKS_REMOVED',
key: uri,
tracks_indexes,
snapshot_id: response.snapshot_id,
});
},
(error) => {
dispatch(coreActions.handleException(
'Could not remove tracks from playlist',
error,
));
},
);
request(
dispatch,
getState,
`playlists/${getFromUri('playlistid', uri)}/tracks`,
'DELETE',
{ snapshot_id, positions: tracks_indexes },
).then(
(response) => {
dispatch({
type: 'PLAYLIST_TRACKS_REMOVED',
key: uri,
tracks_indexes,
snapshot_id: response.snapshot_id,
});
},
(error) => {
dispatch(coreActions.handleException(
'Could not remove tracks from playlist',
error,
));
},
);
};
}

View File

@ -89,11 +89,11 @@ const SpotifyMiddleware = (function () {
store.dispatch(spotifyActions.createPlaylist(action.name, action.description, action.is_private, action.is_collaborative));
break;
case 'SPOTIFY_REMOVE_PLAYLIST_TRACKS':
var playlist = { ...store.getState().core.playlists[action.key] };
store.dispatch(spotifyActions.deleteTracksFromPlaylist(playlist.uri, playlist.snapshot_id, action.tracks_indexes));
case 'SPOTIFY_REMOVE_PLAYLIST_TRACKS': {
const { snapshot_id } = store.getState().core.items[action.key] || {};
store.dispatch(spotifyActions.deleteTracksFromPlaylist(action.key, snapshot_id, action.tracks_indexes));
break;
}
case 'SPOTIFY_ADD_PLAYLIST_TRACKS':
store.dispatch(spotifyActions.addTracksToPlaylist(action.key, action.tracks_uris));

View File

@ -96,7 +96,7 @@ class Search extends React.Component {
}
onSourceClose = () => {
this.search();
this.search(true);
};
digestUri = () => {
@ -125,7 +125,7 @@ class Search extends React.Component {
this.setState({ term: '' });
}
search = () => {
search = (force = false) => {
const {
coreActions: {
startSearch,
@ -133,6 +133,10 @@ class Search extends React.Component {
uiActions: {
setWindowTitle,
},
search_results_query: {
type: existingType,
term: existingTerm,
},
} = this.props;
const {
type,
@ -141,27 +145,11 @@ class Search extends React.Component {
setWindowTitle(i18n('search.title_window', { term: decodeURIComponent(term) }));
/**
* TODO: Searches are being triggered when navigating to type subviews, despite already having
* results. This might be a consequence of having providers merging their results into one array
*/
if (type && term) {
if ((type && term && (force || existingType !== type || existingTerm !== term))) {
startSearch({ type, term });
/*
mopidyActions.getSearchResults(type, term);
if (uri_schemes_search_enabled.includes('spotify:')) {
spotifyActions.getSearchResults(type, term);
}*/
}
}
loadMore = (type) => {
alert(`load more: ${type}`);
// this.props.spotifyActions.getURL(this.props['spotify_'+type+'_more'], 'SPOTIFY_SEARCH_RESULTS_LOADED_MORE_'+type.toUpperCase());
}
setSort = (value) => {
const {
sort,
@ -291,14 +279,41 @@ class Search extends React.Component {
}
}
const mapStateToProps = (state, ownProps) => ({
type: ownProps.match.params.type,
term: ownProps.match.params.term,
uri_schemes_search_enabled: state.ui.uri_schemes_search_enabled || [],
uri_schemes: state.mopidy.uri_schemes || [],
sort: state.ui.search_results_sort || 'followers.total',
sort_reverse: (!!state.ui.search_results_sort_reverse),
});
const mapStateToProps = (state, ownProps) => {
const {
match: {
params: {
type,
term,
},
},
} = ownProps;
const {
mopidy: {
uri_schemes = [],
},
ui: {
uri_schemes_search_enabled = [],
search_results_sort: sort = 'followers.total',
search_results_sort_reverse,
},
core: {
search_results: {
query: search_results_query = {},
} = {},
},
} = state;
return {
type,
term,
uri_schemes,
uri_schemes_search_enabled,
sort,
sort_reverse: !!search_results_sort_reverse,
search_results_query,
};
};
const mapDispatchToProps = (dispatch) => ({
coreActions: bindActionCreators(coreActions, dispatch),