Skip to content

Commit

Permalink
Search results stored by provider:type:term
Browse files Browse the repository at this point in the history
- This allows storing of per-provider, per-type, per-term results
- We can restore old search results, and hide/show by provider without needing to re-query
  • Loading branch information
jaedb committed Oct 8, 2023
1 parent 7493d40 commit b011292
Show file tree
Hide file tree
Showing 15 changed files with 115 additions and 154 deletions.
2 changes: 1 addition & 1 deletion src/js/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const Content = () => (
<Route path="settings/debug" element={<Debug />} />
<Route path="settings/*" element={<Settings />} />
<Route path="search" element={<Search />} />
<Route path="search/:type/:term" element={<Search />} />
<Route path="search/:type/:providers/:term" element={<Search />} />
<Route path="artist/:uri/*" element={<Artist />} />
<Route path="album/:uri/" element={<Album />} />
<Route path="album/:uri/:name" element={<Album />} />
Expand Down
12 changes: 7 additions & 5 deletions src/js/components/SearchResults.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ const SearchResults = ({
type,
all,
}) => {
const { term } = useParams();
const { term, providers = '' } = useParams();
const [sortField, sortReverse] = useSelector(
(state) => getSortSelector(state, SORT_KEY, 'name'),
);
const searchResultsSelector = makeSearchResultsSelector(term, type);
const providersArray = providers.split(',');
const searchResultsSelector = makeSearchResultsSelector(providersArray, term, type);
const rawResults = useSelector(searchResultsSelector);
console.debug(rawResults, providersArray, term, type)
const encodedTerm = encodeURIComponent(term);
let results = [...rawResults];

Expand All @@ -43,7 +45,7 @@ const SearchResults = ({
<h4>
{!all && (
<span>
<URILink uri={`iris:search:all:${encodedTerm}`} uriType="search" unencoded>
<URILink uri={`iris:search:all:all:${encodedTerm}`} uriType="search" unencoded>
<I18n path="search.title" />
</URILink>
{' '}
Expand All @@ -53,7 +55,7 @@ const SearchResults = ({
</span>
)}
{all && (
<URILink uri={`iris:search:${type}:${encodedTerm}`} uriType="search" unencoded>
<URILink uri={`iris:search:${type}:${providers}:${encodedTerm}`} uriType="search" unencoded>
<I18n path={`search.${type}.title`} />
</URILink>
)}
Expand All @@ -66,7 +68,7 @@ const SearchResults = ({
{type === 'tracks' && (
<TrackList
source={{
uri: `iris:search:${type}:${encodedTerm}`,
uri: `iris:search:${type}:${providers}:${encodedTerm}`,
name: 'Search results',
type: 'search',
}}
Expand Down
2 changes: 1 addition & 1 deletion src/js/locale/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ search:
title_window: 'Search: %{term}'
context_actions:
sort: Sort
source: 'Sources (%{count})'
source: Sources
placeholder: Search
all:
title: All
Expand Down
5 changes: 2 additions & 3 deletions src/js/services/core/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,10 @@ export function startSearch(query) {
};
}

export function searchResultsLoaded(query, resultType, results) {
export function searchResultsLoaded(key, results) {
return {
type: 'SEARCH_RESULTS_LOADED',
query,
resultType,
key,
results,
};
}
Expand Down
53 changes: 5 additions & 48 deletions src/js/services/core/middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,79 +177,36 @@ const CoreMiddleware = (function () {

case 'START_SEARCH': {
const { query } = action;
const { term = '', providers = [], type = 'all' } = query;
const {
ui: {
allow_reporting,
},
mopidy: {
uri_schemes = [],
} = {},
} = store.getState();

if (allow_reporting) {
ReactGA.event({
category: 'Search',
action: 'Started',
label: `${query.type}: ${query.term}`,
label: `${type}: ${term}`,
});
}

console.info(`Searching for ${query.type} matching "${query.term}"`);
console.info(`Searching ${providers.length} providers for ${type} matching "${term}"`);

// Trigger reducer immediately; this will hose out any previous results
next(action);

if (uri_schemes.includes('spotify:')) {
if (providers.includes('spotify:')) {
store.dispatch(spotifyActions.getSearchResults(query));
}
store.dispatch(mopidyActions.getSearchResults(
query,
100,
uri_schemes.filter((i) => i !== 'spotify:'), // Omit Spotify; handled above
providers.filter((i) => i !== 'spotify:'), // Omit Spotify; handled above
));
break;
}

case 'SEARCH_RESULTS_LOADED': {
const {
query: {
term,
type,
},
resultType,
results,
} = action;
const {
core: {
search_results: {
query: {
term: prevTerm,
type: prevType,
} = {},
...allResults
} = {},
} = {},
} = store.getState();

// Add to our existing results, so long as the search term is the same
const search_results = {
query: { term, type },
...(term === prevTerm && type === prevType ? allResults : {}),
};

// Merge our new results with the existing (if any)
search_results[resultType] = [
...(search_results[resultType] || []),
...results,
];

next({
...action,
search_results,
});
break;
}

case 'PLAYLIST_TRACKS_ADDED': {
const {
key,
Expand Down
18 changes: 5 additions & 13 deletions src/js/services/core/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,23 +176,15 @@ export default function reducer(core = {}, action) {
/**
* Search results
* */
case 'START_SEARCH':
return {
...core,
search_results: {
query: action.query,
artists: [],
albums: [],
playlists: [],
tracks: [],
},
};

case 'SEARCH_RESULTS_LOADED': {
const { search_results } = action;
console.debug(action)
return {
...core,
search_results,
search_results: {
...core?.search_results || {},
[action.key]: action.results,
},
};
}

Expand Down
4 changes: 2 additions & 2 deletions src/js/services/mopidy/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -591,12 +591,12 @@ export function clearSearchResults() {
};
}

export function getSearchResults(query, limit = 100, uri_schemes) {
export function getSearchResults(query, providers, limit = 100) {
return {
type: 'MOPIDY_GET_SEARCH_RESULTS',
query,
providers,
limit,
uri_schemes,
};
}

Expand Down
37 changes: 19 additions & 18 deletions src/js/services/mopidy/middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
uriSource,
setFavicon,
titleCase,
getSearchResultKey,
} from '../../util/helpers';
import {
digestMopidyImages,
Expand Down Expand Up @@ -263,10 +264,11 @@ const MopidyMiddleware = (function () {
type,
term,
requestType,
uri_scheme,
provider,
method = 'library.search',
data,
} = queue.shift();
const resultKey = getSearchResultKey({ provider, type, term });
const processKey = 'MOPIDY_GET_SEARCH_RESULTS';
const processor = store.getState().ui.processes[processKey];

Expand All @@ -281,7 +283,7 @@ const MopidyMiddleware = (function () {
content: i18n(
'services.mopidy.searching',
{
provider: titleCase(uri_scheme.replace(':', '')),
provider: titleCase(provider.replace(':', '')),
type: requestType,
},
),
Expand Down Expand Up @@ -348,7 +350,7 @@ const MopidyMiddleware = (function () {
playlists: (response) => {
const playlists = response.filter(
(item) => {
if (!item.uri.includes(uri_scheme)) return false;
if (!item.uri.includes(provider)) return false;
return item.name.toLowerCase().includes(term.toLowerCase());
},
);
Expand All @@ -371,8 +373,7 @@ const MopidyMiddleware = (function () {
(response) => {
if (response.length > 0) {
store.dispatch(coreActions.searchResultsLoaded(
{ term, type },
requestType,
resultKey,
processResults[requestType](response),
));
}
Expand Down Expand Up @@ -1221,35 +1222,35 @@ const MopidyMiddleware = (function () {

case 'MOPIDY_GET_SEARCH_RESULTS': {
const {
uri_schemes = [],
query = {},
query: { term, type: queryType } = {},
providers,
} = action;
const types = query.type === 'all'
const types = queryType === 'all'
? ['artists', 'albums', 'tracks', 'playlists']
: [query.type];
: [queryType];

const queue = [];
uri_schemes.forEach(
(uri_scheme) => types.forEach(
providers.forEach(
(provider) => types.forEach(
(type) => {
const item = {
type: query.type,
term: query.term,
type,
term,
provider,
requestType: type,
uri_scheme,
data: {
uris: [uri_scheme],
uris: [provider],
},
};
switch (type) {
case 'tracks':
item.data.query = { any: [query.term] };
item.data.query = { any: [term] };
break;
case 'artists':
item.data.query = { artist: [query.term] };
item.data.query = { artist: [term] };
break;
case 'albums':
item.data.query = { album: [query.term] };
item.data.query = { album: [term] };
break;
case 'playlists':
// Searching for playlists is not supported, so we get a simple
Expand Down
27 changes: 0 additions & 27 deletions src/js/services/mopidy/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,33 +103,6 @@ export default function reducer(mopidy = {}, action) {
directory: { ...mopidy.directory, ...action.directory },
};

/**
* Searching
* */
case 'MOPIDY_CLEAR_SEARCH_RESULTS':
return { ...mopidy, search_results: {} };

case 'MOPIDY_SEARCH_RESULTS_LOADED':
// Fetch or create our container
if (mopidy.search_results) {
var search_results = { ...mopidy.search_results };
} else {
var search_results = {};
}

search_results = {
...search_results,
query: action.query,
};

if (search_results[action.context]) {
search_results[action.context] = [...search_results[action.context], ...action.results];
} else {
search_results[action.context] = action.results;
}

return { ...mopidy, search_results };

default:
return mopidy;
}
Expand Down
16 changes: 7 additions & 9 deletions src/js/services/spotify/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
getFromUri,
uriType,
upgradeSpotifyPlaylistUris,
getSearchResultKey,
} from '../../util/helpers';
import {
formatPlaylistGroup,
Expand Down Expand Up @@ -613,7 +614,8 @@ export function getMore(endpoint, core_action = null, custom_action = null, extr
};
}

export function getSearchResults({ type, term }, limit = 50, offset = 0) {
export function getSearchResults(query, limit = 50, offset = 0) {
const { type, term } = query;
const processKey = 'SPOTIFY_GET_SEARCH_RESULTS';
return (dispatch, getState) => {
const {
Expand Down Expand Up @@ -641,24 +643,21 @@ export function getSearchResults({ type, term }, limit = 50, offset = 0) {
(response) => {
if (response.tracks !== undefined) {
dispatch(coreActions.searchResultsLoaded(
{ term, type },
'tracks',
getSearchResultKey({ provider: 'spotify', type: 'tracks', term }),
formatTracks(response.tracks.items),
));
}

if (response.artists !== undefined) {
dispatch(coreActions.searchResultsLoaded(
{ term, type },
'artists',
getSearchResultKey({ provider: 'spotify', type: 'artists', term }),
formatArtists(response.artists.items),
));
}

if (response.albums !== undefined) {
dispatch(coreActions.searchResultsLoaded(
{ term, type },
'albums',
getSearchResultKey({ provider: 'spotify', type: 'albums', term }),
formatAlbums(response.albums.items),
));
}
Expand All @@ -669,8 +668,7 @@ export function getSearchResults({ type, term }, limit = 50, offset = 0) {
can_edit: (meId === item.owner.id),
}));
dispatch(coreActions.searchResultsLoaded(
{ term, type },
'playlists',
getSearchResultKey({ provider: 'spotify', type: 'playlists', term }),
playlists,
));
}
Expand Down
Loading

0 comments on commit b011292

Please sign in to comment.