2022-09-16 12:47:59 -04:00
|
|
|
import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client';
|
2022-10-28 01:09:59 -04:00
|
|
|
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
|
|
|
import { getItemsApi } from '@jellyfin/sdk/lib/utils/api/items-api';
|
|
|
|
import { ItemSortBy } from '@jellyfin/sdk/lib/models/api/item-sort-by';
|
2022-01-30 00:27:26 +03:00
|
|
|
import escapeHtml from 'escape-html';
|
2021-06-11 14:49:57 +02:00
|
|
|
import React, { FunctionComponent, useEffect, useState } from 'react';
|
2021-06-02 10:00:24 -04:00
|
|
|
|
2023-05-01 10:04:13 -04:00
|
|
|
import { appRouter } from '../router/appRouter';
|
2022-10-28 01:09:59 -04:00
|
|
|
import { useApi } from '../../hooks/useApi';
|
2021-06-02 10:00:24 -04:00
|
|
|
import globalize from '../../scripts/globalize';
|
|
|
|
|
2021-06-07 11:55:01 -04:00
|
|
|
import '../../elements/emby-button/emby-button';
|
|
|
|
|
2021-06-02 10:00:24 -04:00
|
|
|
// There seems to be some compatibility issues here between
|
|
|
|
// React and our legacy web components, so we need to inject
|
|
|
|
// them as an html string for now =/
|
2022-02-18 14:27:39 +03:00
|
|
|
const createSuggestionLink = ({ name, href }: { name: string, href: string }) => ({
|
2021-06-02 10:00:24 -04:00
|
|
|
__html: `<a
|
|
|
|
is='emby-linkbutton'
|
|
|
|
class='button-link'
|
|
|
|
style='display: inline-block; padding: 0.5em 1em;'
|
|
|
|
href='${href}'
|
2022-01-30 00:27:26 +03:00
|
|
|
>${escapeHtml(name)}</a>`
|
2021-06-02 10:00:24 -04:00
|
|
|
});
|
|
|
|
|
2021-06-11 14:49:57 +02:00
|
|
|
type SearchSuggestionsProps = {
|
2022-04-14 01:19:27 -04:00
|
|
|
parentId?: string | null;
|
2023-05-02 15:54:53 -04:00
|
|
|
};
|
2021-06-11 14:49:57 +02:00
|
|
|
|
2022-10-28 01:09:59 -04:00
|
|
|
const SearchSuggestions: FunctionComponent<SearchSuggestionsProps> = ({ parentId }: SearchSuggestionsProps) => {
|
2022-02-15 23:49:46 +03:00
|
|
|
const [ suggestions, setSuggestions ] = useState<BaseItemDto[]>([]);
|
2022-11-18 12:55:46 -05:00
|
|
|
const { api, user } = useApi();
|
2021-06-02 10:00:24 -04:00
|
|
|
|
|
|
|
useEffect(() => {
|
2022-10-28 01:09:59 -04:00
|
|
|
if (api && user?.Id) {
|
|
|
|
getItemsApi(api)
|
2024-03-26 11:04:58 -04:00
|
|
|
.getItems({
|
2022-10-28 01:09:59 -04:00
|
|
|
userId: user.Id,
|
|
|
|
sortBy: [ItemSortBy.IsFavoriteOrLiked, ItemSortBy.Random],
|
|
|
|
includeItemTypes: [BaseItemKind.Movie, BaseItemKind.Series, BaseItemKind.MusicArtist],
|
|
|
|
limit: 20,
|
|
|
|
recursive: true,
|
|
|
|
imageTypeLimit: 0,
|
|
|
|
enableImages: false,
|
|
|
|
parentId: parentId || undefined,
|
|
|
|
enableTotalRecordCount: false
|
|
|
|
})
|
2023-05-02 11:24:53 -04:00
|
|
|
.then(result => setSuggestions(result.data.Items || []))
|
|
|
|
.catch(err => {
|
|
|
|
console.error('[SearchSuggestions] failed to fetch search suggestions', err);
|
|
|
|
setSuggestions([]);
|
|
|
|
});
|
2022-10-28 01:09:59 -04:00
|
|
|
}
|
2022-11-18 12:55:46 -05:00
|
|
|
}, [ api, parentId, user ]);
|
2021-06-02 10:00:24 -04:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className='verticalSection searchSuggestions'
|
|
|
|
style={{ textAlign: 'center' }}
|
|
|
|
>
|
|
|
|
<div>
|
|
|
|
<h2 className='sectionTitle padded-left padded-right'>
|
|
|
|
{globalize.translate('Suggestions')}
|
|
|
|
</h2>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className='searchSuggestionsList padded-left padded-right'>
|
|
|
|
{suggestions.map(item => (
|
|
|
|
<div
|
|
|
|
key={`suggestion-${item.Id}`}
|
|
|
|
dangerouslySetInnerHTML={createSuggestionLink({
|
2022-02-18 14:27:39 +03:00
|
|
|
name: item.Name || '',
|
2021-06-02 10:00:24 -04:00
|
|
|
href: appRouter.getRouteUrl(item)
|
|
|
|
})}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default SearchSuggestions;
|