Splitting out library utils, fixing spread of null, should fix #629

This commit is contained in:
James Barnsley
2020-11-04 21:21:57 +13:00
parent bc38862564
commit 111efe6130
2 changed files with 168 additions and 114 deletions

View File

@ -4,7 +4,13 @@ import localForage from 'localforage';
import { compact } from 'lodash';
import { arrayOf } from '../../util/arrays';
import URILink from '../../components/URILink';
import { uriSource, upgradeSpotifyPlaylistUris, uriType, titleCase } from '../../util/helpers';
import {
uriSource,
upgradeSpotifyPlaylistUris,
uriType,
titleCase,
} from '../../util/helpers';
import { ensureLoaded } from '../../util/library';
import {
formatTracks,
formatTrack,
@ -18,114 +24,6 @@ const mopidyActions = require('../mopidy/actions.js');
const googleActions = require('../google/actions.js');
const spotifyActions = require('../spotify/actions.js');
/**
* Ensure we have an item in our index
* If it's not there, attempt to fetch it from our cold storage
* If it's not their either, call the provided fetch()
*
* @param {*} Object { store, action, fetch, dependents}
*/
const ensureLoaded = ({
store,
containerName = 'items',
action,
fetch,
dependents = [],
fullDependents = [],
}) => {
const {
uri,
options: {
forceRefetch,
full,
},
} = action;
const {
core: {
[containerName]: {
[uri]: item,
} = {},
} = {},
} = store.getState();
const getMissingDependents = (parent) => {
const allDependents = [...dependents, ...fullDependents];
if (!parent) return allDependents;
if (full) {
return allDependents.filter((dep) => parent[dep] === undefined || parent[dep] === null);
}
return dependents.filter((dep) => parent[dep] === undefined || parent[dep] === null);
};
const getDependentUris = (parent) => {
if (!parent) return [];
return [...dependents, ...fullDependents].reduce(
(acc, dependent) => {
return [
...acc,
...(dependent.match(new RegExp('(.*)_uri(.*)')) ? parent[dependent] : []),
];
},
[],
);
};
// Forced refetch bypasses everything
if (forceRefetch) {
console.info(`Force-refetching "${uri}"`);
fetch();
return;
}
// Item already in our index?
if (item) {
if (getMissingDependents(item).length === 0) {
store.dispatch(uiActions.stopLoading(uri));
console.info(`"${uri}" already in index`);
const dependentUris = getDependentUris(item);
if (dependentUris.length) {
console.log(`Loading ${dependentUris.length} dependents`);
store.dispatch(coreActions.loadItems(dependentUris));
}
return;
}
}
// What about in the coldstore?
localForage.getItem(uri).then((restoredItem) => {
if (!restoredItem || getMissingDependents(restoredItem).length > 0) {
fetch();
return;
}
console.info(`Restoring "${uri}" from database`);
store.dispatch(coreActions.restoreItemsFromColdStore([restoredItem]));
// We already have the dependents of our restored item, so restore them.
// We assume that because THIS item is in the coldstore, its dependents
// are as well.
const dependentUris = getDependentUris(restoredItem);
if (dependentUris.length > 0) {
console.info(`Restoring ${dependentUris.length} dependents from database`);
const restoreAllDependents = dependentUris.map(
(dependentUri) => localForage.getItem(dependentUri),
);
Promise.all(restoreAllDependents).then(
(dependentItems) => {
store.dispatch(
coreActions.restoreItemsFromColdStore(
compact(dependentItems), // Squash nulls (ie items not found in coldstore)
),
);
},
);
}
});
};
const CoreMiddleware = (function () {
return (store) => (next) => (action = {}) => {
const {
@ -352,10 +250,6 @@ const CoreMiddleware = (function () {
break;
}
case 'RESTART':
location.reload();
break;
case 'PLAYLIST_TRACKS_ADDED': {
const {
key,
@ -378,7 +272,6 @@ const CoreMiddleware = (function () {
switch (uriSource(key)) {
case 'spotify':
console.log("GETTING", key)
store.dispatch(spotifyActions.getPlaylist(key));
break;
case 'm3u':

161
src/js/util/library.js Normal file
View File

@ -0,0 +1,161 @@
import { compact } from 'lodash';
import localForage from 'localforage';
const coreActions = require('../services/core/actions.js');
const uiActions = require('../services/ui/actions.js');
/**
* Inspect object to check for missing dependent properties
*
* @param {Object} = item, dependents, fullDependents, full
*/
const getMissingDependents = ({
item,
dependents = [],
fullDependents = [],
full,
}) => {
const allDependents = [
...dependents,
...fullDependents,
];
if (!item) return allDependents;
if (full) {
return allDependents.filter((dep) => item[dep] === undefined || item[dep] === null);
}
return dependents.filter((dep) => item[dep] === undefined || item[dep] === null);
};
/**
* Pluck all the URIs out of our dependent properties.
*
* @param {Object} = item, dependents, fullDependents
*/
const getDependentUris = ({
item,
dependents = [],
fullDependents = [],
}) => {
if (!item) return [];
return [...dependents, ...fullDependents].reduce(
(acc, dep) => [
...acc,
...(dep.match(new RegExp('(.*)_uri(.*)')) ? item[dep] : []),
],
[],
);
};
/**
* Ensure we have an item in our index
* If it's not there, attempt to fetch it from our cold storage
* If it's not their either, call the provided fetch()
*
* @param {*} Object { store, action, fetch, dependents}
*/
const ensureLoaded = ({
store,
containerName = 'items',
action,
fetch,
dependents = [],
fullDependents = [],
}) => {
const {
uri,
options: {
forceRefetch,
full,
},
} = action;
const {
core: {
[containerName]: {
[uri]: item,
} = {},
} = {},
} = store.getState();
// Forced refetch bypasses everything
if (forceRefetch) {
console.info(`Force-refetching "${uri}"`);
fetch();
return;
}
const missingDependents = (itemToCheck) => getMissingDependents({
item: itemToCheck,
dependents,
fullDependents,
full,
});
const dependentUris = (itemToCheck) => getDependentUris({
item: itemToCheck,
dependents,
fullDependents,
});
// Item already in our index?
if (item) {
if (missingDependents(item).length === 0) {
store.dispatch(uiActions.stopLoading(uri));
console.info(`"${uri}" already in index`);
const uris = dependentUris(item);
if (uris.length) {
console.log(`Loading ${uris.length} dependents`);
store.dispatch(coreActions.loadItems(uris));
}
return;
}
}
// What about in the coldstore?
localForage.getItem(uri).then((restoredItem) => {
if (
!restoredItem ||
missingDependents(restoredItem).length > 0
) {
fetch();
return;
}
console.info(`Restoring "${uri}" from database`);
store.dispatch(coreActions.restoreItemsFromColdStore([restoredItem]));
// We already have the dependents of our restored item, so restore them.
// We assume that because THIS item is in the coldstore, its dependents
// are as well.
const uris = dependentUris(restoredItem);
if (uris.length > 0) {
console.info(`Restoring ${uris.length} dependents from database`);
const restoreAllDependents = uris.map(
(dependentUri) => localForage.getItem(dependentUri),
);
Promise.all(restoreAllDependents).then(
(dependentItems) => {
store.dispatch(
coreActions.restoreItemsFromColdStore(
compact(dependentItems), // Squash nulls (ie items not found in coldstore)
),
);
},
);
}
});
};
export {
getMissingDependents,
getDependentUris,
ensureLoaded,
};
export default {
getMissingDependents,
getDependentUris,
ensureLoaded,
};