diff --git a/package-lock.json b/package-lock.json
index c280d080d..652a9cc9f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3010,6 +3010,11 @@
"version": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
"integrity": "sha512-5rjszPzcjFVoDEOarszcbax2WIGT3+fO+W212ZWg9+ylGJgxG1IIcCFjnnBbSdM0lNeIfmMGhhEGovIlr+1yBg=="
},
+ "classnames": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
+ "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
+ },
"clean-css": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
diff --git a/package.json b/package.json
index 218e2b090..6cc0f8de3 100644
--- a/package.json
+++ b/package.json
@@ -58,6 +58,7 @@
"@fontsource/noto-sans-sc": "^4.2.1",
"blurhash": "^1.1.3",
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
+ "classnames": "^2.3.1",
"core-js": "^3.11.2",
"date-fns": "^2.21.1",
"epubjs": "^0.3.85",
diff --git a/src/components/pages/SearchPage.js b/src/components/pages/SearchPage.js
index ea37bfec5..93e277988 100644
--- a/src/components/pages/SearchPage.js
+++ b/src/components/pages/SearchPage.js
@@ -2,8 +2,9 @@ import PropTypes from 'prop-types';
import React, { useState } from 'react';
import SearchFields from '../search/SearchFields';
-import SearchResults from '../search/SearchResultsComponent';
+import SearchResults from '../search/SearchResults';
import SearchSuggestions from '../search/SearchSuggestions';
+import LiveTVSearchResults from '../search/LiveTVSearchResults';
const SearchPage = ({ serverId, parentId, collectionType }) => {
const [ query, setQuery ] = useState(null);
@@ -23,6 +24,12 @@ const SearchPage = ({ serverId, parentId, collectionType }) => {
collectionType={collectionType}
query={query}
/>
+
>
);
};
diff --git a/src/components/search/LiveTVSearchResults.js b/src/components/search/LiveTVSearchResults.js
new file mode 100644
index 000000000..c4ffa6a51
--- /dev/null
+++ b/src/components/search/LiveTVSearchResults.js
@@ -0,0 +1,195 @@
+import classNames from 'classnames';
+import PropTypes from 'prop-types';
+import React, { useEffect, useState } from 'react';
+
+import globalize from '../../scripts/globalize';
+import ServerConnections from '../ServerConnections';
+import SearchResultsRow from './SearchResultsRow';
+
+const CARD_OPTIONS = {
+ preferThumb: true,
+ inheritThumb: false,
+ showParentTitleOrTitle: true,
+ showTitle: false,
+ coverImage: true,
+ overlayMoreButton: true,
+ showAirTime: true,
+ showAirDateTime: true,
+ showChannelName: true
+};
+
+const LiveTVSearchResults = ({ serverId, parentId, collectionType, query }) => {
+ const [ apiClient, setApiClient ] = useState();
+ const [ movies, setMovies ] = useState([]);
+ const [ episodes, setEpisodes ] = useState([]);
+ const [ sports, setSports ] = useState([]);
+ const [ kids, setKids ] = useState([]);
+ const [ news, setNews ] = useState([]);
+ const [ programs, setPrograms ] = useState([]);
+ const [ videos, setVideos ] = useState([]);
+
+ const getDefaultParameters = () => ({
+ ParentId: parentId,
+ searchTerm: query,
+ Limit: 24,
+ Fields: 'PrimaryImageAspectRatio,CanDelete,BasicSyncInfo,MediaSourceCount',
+ Recursive: true,
+ EnableTotalRecordCount: false,
+ ImageTypeLimit: 1,
+ IncludePeople: false,
+ IncludeMedia: false,
+ IncludeGenres: false,
+ IncludeStudios: false,
+ IncludeArtists: false
+ });
+
+ // FIXME: This query does not support Live TV filters
+ const fetchItems = (apiClient, params = {}) => apiClient?.getItems(
+ apiClient?.getCurrentUserId(),
+ {
+ ...getDefaultParameters(),
+ IncludeMedia: true,
+ ...params
+ }
+ );
+
+ const isLiveTV = () => collectionType === 'livetv';
+
+ useEffect(() => {
+ if (serverId) setApiClient(ServerConnections.getApiClient(serverId));
+ }, [ serverId ]);
+
+ useEffect(() => {
+ // Reset state
+ setMovies([]);
+ setEpisodes([]);
+ setSports([]);
+ setKids([]);
+ setNews([]);
+ setPrograms([]);
+ setVideos([]);
+
+ if (query && isLiveTV()) {
+ // Movies row
+ fetchItems(apiClient, {
+ IncludeItemTypes: 'LiveTvProgram',
+ IsMovie: true,
+ IsSeries: false,
+ IsSports: false,
+ IsKids: false,
+ IsNews: false
+ }).then(result => setMovies(result.Items));
+ // Episodes row
+ fetchItems(apiClient, {
+ IncludeItemTypes: 'LiveTvProgram',
+ IsMovie: false,
+ IsSeries: true,
+ IsSports: false,
+ IsKids: false,
+ IsNews: false
+ }).then(result => setEpisodes(result.Items));
+ // Sports row
+ fetchItems(apiClient, {
+ IncludeItemTypes: 'LiveTvProgram',
+ IsMovie: false,
+ IsSeries: false,
+ IsSports: true,
+ IsKids: false,
+ IsNews: false
+ }).then(result => setSports(result.Items));
+ // Kids row
+ fetchItems(apiClient, {
+ IncludeItemTypes: 'LiveTvProgram',
+ IsMovie: false,
+ IsSeries: false,
+ IsSports: false,
+ IsKids: true,
+ IsNews: false
+ }).then(result => setKids(result.Items));
+ // News row
+ fetchItems(apiClient, {
+ IncludeItemTypes: 'LiveTvProgram',
+ IsMovie: false,
+ IsSeries: false,
+ IsSports: false,
+ IsKids: false,
+ IsNews: true
+ }).then(result => setNews(result.Items));
+ // Programs row
+ fetchItems(apiClient, {
+ IncludeItemTypes: 'LiveTvProgram',
+ IsMovie: false,
+ IsSeries: false,
+ IsSports: false,
+ IsKids: false,
+ IsNews: false
+ }).then(result => setPrograms(result.Items));
+ // NOTE: I believe this is supposed to be home videos, but it
+ // includes TV channels so it should probably be included for Live TV
+ // Videos row
+ fetchItems(apiClient, {
+ MediaTypes: 'Video',
+ ExcludeItemTypes: 'Movie,Episode'
+ }).then(result => setVideos(result.Items));
+ }
+ }, [ query ]);
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
+
+LiveTVSearchResults.propTypes = {
+ serverId: PropTypes.string,
+ parentId: PropTypes.string,
+ collectionType: PropTypes.string,
+ query: PropTypes.string
+};
+
+export default LiveTVSearchResults;
diff --git a/src/components/search/SearchResults.js b/src/components/search/SearchResults.js
new file mode 100644
index 000000000..daf32d477
--- /dev/null
+++ b/src/components/search/SearchResults.js
@@ -0,0 +1,258 @@
+import classNames from 'classnames';
+import PropTypes from 'prop-types';
+import React, { useEffect, useState } from 'react';
+
+import globalize from '../../scripts/globalize';
+import ServerConnections from '../ServerConnections';
+import SearchResultsRow from './SearchResultsRow';
+
+const SearchResultsComponent = ({ serverId, parentId, collectionType, query }) => {
+ const [ apiClient, setApiClient ] = useState();
+ const [ movies, setMovies ] = useState([]);
+ const [ shows, setShows ] = useState([]);
+ const [ episodes, setEpisodes ] = useState([]);
+ const [ programs, setPrograms ] = useState([]);
+ const [ videos, setVideos ] = useState([]);
+ const [ playlists, setPlaylists ] = useState([]);
+ const [ artists, setArtists ] = useState([]);
+ const [ albums, setAlbums ] = useState([]);
+ const [ songs, setSongs ] = useState([]);
+ const [ photoAlbums, setPhotoAlbums ] = useState([]);
+ const [ photos, setPhotos ] = useState([]);
+ const [ audioBooks, setAudioBooks ] = useState([]);
+ const [ books, setBooks ] = useState([]);
+ const [ people, setPeople ] = useState([]);
+
+ const getDefaultParameters = () => ({
+ ParentId: parentId,
+ searchTerm: query,
+ Limit: 24,
+ Fields: 'PrimaryImageAspectRatio,CanDelete,BasicSyncInfo,MediaSourceCount',
+ Recursive: true,
+ EnableTotalRecordCount: false,
+ ImageTypeLimit: 1,
+ IncludePeople: false,
+ IncludeMedia: false,
+ IncludeGenres: false,
+ IncludeStudios: false,
+ IncludeArtists: false
+ });
+
+ const fetchArtists = (apiClient, params = {}) => apiClient?.getArtists(
+ apiClient?.getCurrentUserId(),
+ {
+ ...getDefaultParameters(),
+ IncludeArtists: true,
+ ...params
+ }
+ );
+
+ const fetchItems = (apiClient, params = {}) => apiClient?.getItems(
+ apiClient?.getCurrentUserId(),
+ {
+ ...getDefaultParameters(),
+ IncludeMedia: true,
+ ...params
+ }
+ );
+
+ const fetchPeople = (apiClient, params = {}) => apiClient?.getPeople(
+ apiClient?.getCurrentUserId(),
+ {
+ ...getDefaultParameters(),
+ IncludePeople: true,
+ ...params
+ }
+ );
+
+ const isMovies = () => collectionType === 'movies';
+
+ const isMusic = () => collectionType === 'music';
+
+ const isTVShows = () => collectionType === 'tvshows' || collectionType === 'tv';
+
+ useEffect(() => {
+ if (serverId) setApiClient(ServerConnections.getApiClient(serverId));
+ }, [ serverId ]);
+
+ useEffect(() => {
+ // Reset state
+ setMovies([]);
+ setShows([]);
+ setEpisodes([]);
+ setPrograms([]);
+ setVideos([]);
+ setPlaylists([]);
+ setArtists([]);
+ setAlbums([]);
+ setSongs([]);
+ setPhotoAlbums([]);
+ setPhotos([]);
+ setAudioBooks([]);
+ setBooks([]);
+ setPeople([]);
+
+ if (query) {
+ // Movie libraries
+ if (!collectionType || isMovies()) {
+ // Movies row
+ fetchItems(apiClient, { IncludeItemTypes: 'Movie' })
+ .then(result => setMovies(result.Items));
+ }
+
+ // TV Show libraries
+ if (!collectionType || isTVShows()) {
+ // Shows row
+ fetchItems(apiClient, { IncludeItemTypes: 'Series' })
+ .then(result => setShows(result.Items));
+ // Episodes row
+ fetchItems(apiClient, { IncludeItemTypes: 'Episode' })
+ .then(result => setEpisodes(result.Items));
+ }
+
+ // People are included for Movies and TV Shows
+ if (!collectionType || isMovies() || isTVShows()) {
+ // People row
+ fetchPeople(apiClient).then(result => setPeople(result.Items));
+ }
+
+ // Music libraries
+ if (!collectionType || isMusic()) {
+ // Playlists row
+ fetchItems(apiClient, { IncludeItemTypes: 'Playlist' })
+ .then(results => setPlaylists(results.Items));
+ // Artists row
+ fetchArtists(apiClient).then(result => setArtists(result.Items));
+ // Albums row
+ fetchItems(apiClient, { IncludeItemTypes: 'MusicAlbum' })
+ .then(result => setAlbums(result.Items));
+ // Songs row
+ fetchItems(apiClient, { IncludeItemTypes: 'Audio' })
+ .then(result => setSongs(result.Items));
+ }
+
+ // Other libraries do not support in-library search currently
+ if (!collectionType) {
+ // Programs row
+ fetchItems(apiClient, { IncludeItemTypes: 'LiveTvProgram' })
+ .then(result => setPrograms(result.Items));
+ // Videos row
+ fetchItems(apiClient, {
+ MediaTypes: 'Video',
+ ExcludeItemTypes: 'Movie,Episode'
+ }).then(result => setVideos(result.Items));
+ // Photo Albums row
+ fetchItems(apiClient, { IncludeItemTypes: 'PhotoAlbum' })
+ .then(results => setPhotoAlbums(results.Items));
+ // Photos row
+ fetchItems(apiClient, { IncludeItemTypes: 'Photo' })
+ .then(results => setPhotos(results.Items));
+ // Audio Books row
+ fetchItems(apiClient, { IncludeItemTypes: 'AudioBook' })
+ .then(results => setAudioBooks(results.Items));
+ // Books row
+ fetchItems(apiClient, { IncludeItemTypes: 'Book' })
+ .then(results => setBooks(results.Items));
+ }
+ }
+ }, [ query ]);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+SearchResultsComponent.propTypes = {
+ serverId: PropTypes.string,
+ parentId: PropTypes.string,
+ collectionType: PropTypes.string,
+ query: PropTypes.string
+};
+
+export default SearchResultsComponent;
diff --git a/src/components/search/SearchResultsComponent.js b/src/components/search/SearchResultsComponent.js
deleted file mode 100644
index 925d74987..000000000
--- a/src/components/search/SearchResultsComponent.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { useEffect, useRef, useState } from 'react';
-
-import SearchResults from './searchresults';
-
-const SearchResultsComponent = ({ serverId, parentId, collectionType, query }) => {
- const [ searchResults, setSearchResults ] = useState(null);
- const searchResultsElement = useRef(null);
-
- useEffect(() => {
- setSearchResults(
- new SearchResults({
- element: searchResultsElement.current,
- serverId: serverId || ApiClient.serverId(),
- parentId,
- collectionType
- })
- );
-
- return () => {
- searchResults?.destroy();
- };
- }, []);
-
- useEffect(() => {
- searchResults?.search(query);
- }, [ query ]);
-
- return (
-
- );
-};
-
-SearchResultsComponent.propTypes = {
- serverId: PropTypes.string,
- parentId: PropTypes.string,
- collectionType: PropTypes.string,
- query: PropTypes.string
-};
-
-export default SearchResultsComponent;
diff --git a/src/components/search/SearchResultsRow.js b/src/components/search/SearchResultsRow.js
new file mode 100644
index 000000000..df40154cb
--- /dev/null
+++ b/src/components/search/SearchResultsRow.js
@@ -0,0 +1,48 @@
+import PropTypes from 'prop-types';
+import React, { useEffect, useRef } from 'react';
+
+import cardBuilder from '../cardbuilder/cardBuilder';
+
+// 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 =/
+const createScroller = ({ title = '' }) => ({
+ __html: `${title}
+ `
+});
+
+const SearchResultsRow = ({ title, items = [], cardOptions = {} }) => {
+ const element = useRef(null);
+
+ useEffect(() => {
+ cardBuilder.buildCards(items, {
+ itemsContainer: element.current?.querySelector('.itemsContainer'),
+ parentContainer: element.current,
+ shape: 'autooverflow',
+ scalable: true,
+ showTitle: true,
+ overlayText: false,
+ centerText: true,
+ allowBottomPadding: false,
+ ...cardOptions
+ });
+ }, [ items ]);
+
+ return (
+
+ );
+};
+
+SearchResultsRow.propTypes = {
+ title: PropTypes.string,
+ items: PropTypes.array,
+ cardOptions: PropTypes.object
+};
+
+export default SearchResultsRow;
diff --git a/src/components/search/searchresults.js b/src/components/search/searchresults.js
deleted file mode 100644
index 263a2b94c..000000000
--- a/src/components/search/searchresults.js
+++ /dev/null
@@ -1,581 +0,0 @@
-import layoutManager from '../layoutManager';
-import globalize from '../../scripts/globalize';
-import cardBuilder from '../cardbuilder/cardBuilder';
-import '../../elements/emby-scroller/emby-scroller';
-import '../../elements/emby-itemscontainer/emby-itemscontainer';
-import '../../elements/emby-button/emby-button';
-import ServerConnections from '../ServerConnections';
-import template from './searchresults.template.html';
-
-function getSearchHints(instance, apiClient, query) {
- if (!query.searchTerm) {
- return Promise.resolve({
- SearchHints: []
- });
- }
-
- let allowSearch = true;
-
- const queryIncludeItemTypes = query.IncludeItemTypes;
-
- if (instance.options.collectionType === 'tvshows') {
- if (query.IncludeArtists) {
- allowSearch = false;
- } else if (queryIncludeItemTypes === 'Movie' ||
- queryIncludeItemTypes === 'LiveTvProgram' ||
- queryIncludeItemTypes === 'MusicAlbum' ||
- queryIncludeItemTypes === 'Audio' ||
- queryIncludeItemTypes === 'Book' ||
- queryIncludeItemTypes === 'AudioBook' ||
- queryIncludeItemTypes === 'Playlist' ||
- queryIncludeItemTypes === 'PhotoAlbum' ||
- query.MediaTypes === 'Video' ||
- query.MediaTypes === 'Photo') {
- allowSearch = false;
- }
- } else if (instance.options.collectionType === 'movies') {
- if (query.IncludeArtists) {
- allowSearch = false;
- } else if (queryIncludeItemTypes === 'Series' ||
- queryIncludeItemTypes === 'Episode' ||
- queryIncludeItemTypes === 'LiveTvProgram' ||
- queryIncludeItemTypes === 'MusicAlbum' ||
- queryIncludeItemTypes === 'Audio' ||
- queryIncludeItemTypes === 'Book' ||
- queryIncludeItemTypes === 'AudioBook' ||
- queryIncludeItemTypes === 'Playlist' ||
- queryIncludeItemTypes === 'PhotoAlbum' ||
- query.MediaTypes === 'Video' ||
- query.MediaTypes === 'Photo') {
- allowSearch = false;
- }
- } else if (instance.options.collectionType === 'music') {
- if (query.People) {
- allowSearch = false;
- } else if (queryIncludeItemTypes === 'Series' ||
- queryIncludeItemTypes === 'Episode' ||
- queryIncludeItemTypes === 'LiveTvProgram' ||
- queryIncludeItemTypes === 'Movie') {
- allowSearch = false;
- }
- } else if (instance.options.collectionType === 'livetv') {
- if (query.IncludeArtists || query.IncludePeople) {
- allowSearch = false;
- } else if (queryIncludeItemTypes === 'Series' ||
- queryIncludeItemTypes === 'Episode' ||
- queryIncludeItemTypes === 'MusicAlbum' ||
- queryIncludeItemTypes === 'Audio' ||
- queryIncludeItemTypes === 'Book' ||
- queryIncludeItemTypes === 'AudioBook' ||
- queryIncludeItemTypes === 'PhotoAlbum' ||
- queryIncludeItemTypes === 'Movie' ||
- query.MediaTypes === 'Video' ||
- query.MediaTypes === 'Photo') {
- allowSearch = false;
- }
- }
- if (queryIncludeItemTypes === 'NullType') {
- allowSearch = false;
- }
-
- if (!allowSearch) {
- return Promise.resolve({
- SearchHints: []
- });
- }
-
- // Convert the search hint query to a regular item query
- if (apiClient.isMinServerVersion('3.4.1.31')) {
- query.Fields = 'PrimaryImageAspectRatio,CanDelete,BasicSyncInfo,MediaSourceCount';
- query.Recursive = true;
- query.EnableTotalRecordCount = false;
- query.ImageTypeLimit = 1;
-
- let methodName = 'getItems';
-
- if (!query.IncludeMedia) {
- if (query.IncludePeople) {
- methodName = 'getPeople';
- } else if (query.IncludeArtists) {
- methodName = 'getArtists';
- }
- }
-
- return apiClient[methodName](apiClient.getCurrentUserId(), query);
- }
-
- query.UserId = apiClient.getCurrentUserId();
-
- return apiClient.getSearchHints(query);
-}
-
-function search(instance, apiClient, context, value) {
- if (value || layoutManager.tv) {
- instance.mode = 'search';
- } else {
- instance.mode = 'suggestions';
- }
-
- if (instance.options.collectionType === 'livetv') {
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- IncludeItemTypes: 'LiveTvProgram',
- IsMovie: true,
- IsKids: false,
- IsNews: false
-
- }, context, '.movieResults', {
-
- preferThumb: true,
- inheritThumb: false,
- shape: (enableScrollX() ? 'overflowPortrait' : 'portrait'),
- showParentTitleOrTitle: true,
- showTitle: false,
- centerText: true,
- coverImage: true,
- overlayText: false,
- overlayMoreButton: true,
- showAirTime: true,
- showAirDateTime: true,
- showChannelName: true
- });
- } else {
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- IncludeItemTypes: 'Movie'
-
- }, context, '.movieResults', {
-
- showTitle: true,
- overlayText: false,
- centerText: true,
- showYear: true
- });
- }
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- IncludeItemTypes: 'Series'
-
- }, context, '.seriesResults', {
-
- showTitle: true,
- overlayText: false,
- centerText: true,
- showYear: true
- });
-
- if (instance.options.collectionType === 'livetv') {
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- IncludeItemTypes: 'LiveTvProgram',
- IsSeries: true,
- IsSports: false,
- IsKids: false,
- IsNews: false
-
- }, context, '.episodeResults', {
-
- preferThumb: true,
- inheritThumb: false,
- shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'),
- showParentTitleOrTitle: true,
- showTitle: false,
- centerText: true,
- coverImage: true,
- overlayText: false,
- overlayMoreButton: true,
- showAirTime: true,
- showAirDateTime: true,
- showChannelName: true
- });
- } else {
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- IncludeItemTypes: 'Episode'
-
- }, context, '.episodeResults', {
-
- coverImage: true,
- showTitle: true,
- showParentTitle: true
- });
- }
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- // NullType to hide
- IncludeItemTypes: instance.options.collectionType === 'livetv' ? 'LiveTvProgram' : 'NullType',
- IsSports: true
-
- }, context, '.sportsResults', {
-
- preferThumb: true,
- inheritThumb: false,
- shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'),
- showParentTitleOrTitle: true,
- showTitle: false,
- centerText: true,
- coverImage: true,
- overlayText: false,
- overlayMoreButton: true,
- showAirTime: true,
- showAirDateTime: true,
- showChannelName: true
-
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- // NullType to hide
- IncludeItemTypes: instance.options.collectionType === 'livetv' ? 'LiveTvProgram' : 'NullType',
- IsKids: true
-
- }, context, '.kidsResults', {
-
- preferThumb: true,
- inheritThumb: false,
- shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'),
- showParentTitleOrTitle: true,
- showTitle: false,
- centerText: true,
- coverImage: true,
- overlayText: false,
- overlayMoreButton: true,
- showAirTime: true,
- showAirDateTime: true,
- showChannelName: true
-
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- // NullType to hide
- IncludeItemTypes: instance.options.collectionType === 'livetv' ? 'LiveTvProgram' : 'NullType',
- IsNews: true
-
- }, context, '.newsResults', {
-
- preferThumb: true,
- inheritThumb: false,
- shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'),
- showParentTitleOrTitle: true,
- showTitle: false,
- centerText: true,
- coverImage: true,
- overlayText: false,
- overlayMoreButton: true,
- showAirTime: true,
- showAirDateTime: true,
- showChannelName: true
-
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- IncludeItemTypes: 'LiveTvProgram',
- IsMovie: instance.options.collectionType === 'livetv' ? false : null,
- IsSeries: instance.options.collectionType === 'livetv' ? false : null,
- IsSports: instance.options.collectionType === 'livetv' ? false : null,
- IsKids: instance.options.collectionType === 'livetv' ? false : null,
- IsNews: instance.options.collectionType === 'livetv' ? false : null
-
- }, context, '.programResults', {
-
- preferThumb: true,
- inheritThumb: false,
- shape: (enableScrollX() ? 'overflowBackdrop' : 'backdrop'),
- showParentTitleOrTitle: true,
- showTitle: false,
- centerText: true,
- coverImage: true,
- overlayText: false,
- overlayMoreButton: true,
- showAirTime: true,
- showAirDateTime: true,
- showChannelName: true
-
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- MediaTypes: 'Video',
- ExcludeItemTypes: 'Movie,Episode'
-
- }, context, '.videoResults', {
-
- showParentTitle: true,
- showTitle: true,
- overlayText: false,
- centerText: true
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: true,
- IncludeMedia: false,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false
-
- }, context, '.peopleResults', {
-
- coverImage: true,
- showTitle: true
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: false,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: true
-
- }, context, '.artistResults', {
- coverImage: true,
- showTitle: true
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- IncludeItemTypes: 'MusicAlbum'
-
- }, context, '.albumResults', {
-
- showParentTitle: true,
- showTitle: true,
- overlayText: false,
- centerText: true
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- IncludeItemTypes: 'Audio'
-
- }, context, '.songResults', {
-
- showParentTitle: true,
- showTitle: true,
- overlayText: false,
- centerText: true,
- overlayPlayButton: true
-
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- MediaTypes: 'Photo'
-
- }, context, '.photoResults', {
-
- showParentTitle: false,
- showTitle: true,
- overlayText: false,
- centerText: true
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- IncludeItemTypes: 'PhotoAlbum'
-
- }, context, '.photoAlbumResults', {
-
- showTitle: true,
- overlayText: false,
- centerText: true
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- IncludeItemTypes: 'Book'
-
- }, context, '.bookResults', {
-
- showTitle: true,
- overlayText: false,
- centerText: true
-
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- IncludeItemTypes: 'AudioBook'
-
- }, context, '.audioBookResults', {
-
- showTitle: true,
- overlayText: false,
- centerText: true
- });
-
- searchType(instance, apiClient, {
- searchTerm: value,
- IncludePeople: false,
- IncludeMedia: true,
- IncludeGenres: false,
- IncludeStudios: false,
- IncludeArtists: false,
- IncludeItemTypes: 'Playlist'
-
- }, context, '.playlistResults', {
-
- showTitle: true,
- overlayText: false,
- centerText: true
- });
-}
-
-function searchType(instance, apiClient, query, context, section, cardOptions) {
- query.Limit = enableScrollX() ? 24 : 16;
- query.ParentId = instance.options.parentId;
-
- getSearchHints(instance, apiClient, query).then(function (result) {
- populateResults(result, context, section, cardOptions);
- });
-}
-
-function populateResults(result, context, section, cardOptions) {
- section = context.querySelector(section);
-
- const items = result.Items || result.SearchHints;
-
- const itemsContainer = section.querySelector('.itemsContainer');
-
- cardBuilder.buildCards(items, Object.assign({
-
- itemsContainer: itemsContainer,
- parentContainer: section,
- shape: enableScrollX() ? 'autooverflow' : 'auto',
- scalable: true,
- overlayText: false,
- centerText: true,
- allowBottomPadding: !enableScrollX()
-
- }, cardOptions || {}));
-}
-
-function enableScrollX() {
- return true;
-}
-
-function replaceAll(originalString, strReplace, strWith) {
- const reg = new RegExp(strReplace, 'ig');
- return originalString.replace(reg, strWith);
-}
-
-function embed(elem, instance) {
- let workingTemplate = template;
- if (!enableScrollX()) {
- workingTemplate = replaceAll(workingTemplate, 'data-horizontal="true"', 'data-horizontal="false"');
- workingTemplate = replaceAll(workingTemplate, 'itemsContainer scrollSlider', 'itemsContainer scrollSlider vertical-wrap');
- }
-
- const html = globalize.translateHtml(workingTemplate, 'core');
-
- elem.innerHTML = html;
-
- elem.classList.add('searchResults');
- instance.search('');
-}
-
-class SearchResults {
- constructor(options) {
- this.options = options;
- embed(options.element, this);
- }
- search(value) {
- const apiClient = ServerConnections.getApiClient(this.options.serverId);
-
- search(this, apiClient, this.options.element, value);
- }
- destroy() {
- const options = this.options;
- if (options) {
- options.element.classList.remove('searchFields');
- }
- this.options = null;
- }
-}
-
-export default SearchResults;
diff --git a/src/components/search/searchresults.template.html b/src/components/search/searchresults.template.html
deleted file mode 100644
index 1deecaca6..000000000
--- a/src/components/search/searchresults.template.html
+++ /dev/null
@@ -1,145 +0,0 @@
-
-
-
-
${Suggestions}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
${HeaderPhotoAlbums}
-
-
-
-
-
-
-
-
${HeaderAudioBooks}
-
-
-
-
-
-
-