diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 2b4b0aa8214..05b512b8aea 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -70,6 +70,7 @@ - [tehciolo](https://github.com/tehciolo) - [scampower3](https://github.com/scampower3) - [LittleBigOwI] (https://github.com/LittleBigOwI/) + - [Nate G](https://github.com/GGProGaming) # Emby Contributors diff --git a/src/components/search/SearchResults.tsx b/src/components/search/SearchResults.tsx index ebb5240b289..2f4befcc2f2 100644 --- a/src/components/search/SearchResults.tsx +++ b/src/components/search/SearchResults.tsx @@ -6,6 +6,7 @@ import React, { FunctionComponent, useCallback, useEffect, useState } from 'reac import globalize from '../../scripts/globalize'; import ServerConnections from '../ServerConnections'; import SearchResultsRow from './SearchResultsRow'; +import Loading from '../loading/LoadingComponent'; type SearchResultsProps = { serverId?: string; @@ -45,6 +46,7 @@ const SearchResults: FunctionComponent = ({ serverId = windo const [ books, setBooks ] = useState([]); const [ people, setPeople ] = useState([]); const [ collections, setCollections ] = useState([]); + const [isLoading, setIsLoading] = useState(false); const getDefaultParameters = useCallback(() => ({ ParentId: parentId, @@ -114,99 +116,123 @@ const SearchResults: FunctionComponent = ({ serverId = windo setCollections([]); if (!query) { + setIsLoading(false); return; } + setIsLoading(true); + const apiClient = ServerConnections.getApiClient(serverId); + const fetchPromises = []; // Movie libraries if (!collectionType || isMovies(collectionType)) { - // Movies row - fetchItems(apiClient, { IncludeItemTypes: 'Movie' }) - .then(result => setMovies(result.Items)) - .catch(() => setMovies([])); + fetchPromises.push( + // Movies row + fetchItems(apiClient, { IncludeItemTypes: 'Movie' }) + .then(result => setMovies(result.Items)) + .catch(() => setMovies([])) + ); } // TV Show libraries if (!collectionType || isTVShows(collectionType)) { - // Shows row - fetchItems(apiClient, { IncludeItemTypes: 'Series' }) - .then(result => setShows(result.Items)) - .catch(() => setShows([])); - // Episodes row - fetchItems(apiClient, { IncludeItemTypes: 'Episode' }) - .then(result => setEpisodes(result.Items)) - .catch(() => setEpisodes([])); + fetchPromises.push( + // Shows row + fetchItems(apiClient, { IncludeItemTypes: 'Series' }) + .then(result => setShows(result.Items)) + .catch(() => setShows([])), + // Episodes row + fetchItems(apiClient, { IncludeItemTypes: 'Episode' }) + .then(result => setEpisodes(result.Items)) + .catch(() => setEpisodes([])) + ); } // People are included for Movies and TV Shows if (!collectionType || isMovies(collectionType) || isTVShows(collectionType)) { - // People row - fetchPeople(apiClient) - .then(result => setPeople(result.Items)) - .catch(() => setPeople([])); + fetchPromises.push( + // People row + fetchPeople(apiClient) + .then(result => setPeople(result.Items)) + .catch(() => setPeople([])) + ); } // Music libraries if (!collectionType || isMusic(collectionType)) { - // Playlists row - fetchItems(apiClient, { IncludeItemTypes: 'Playlist' }) - .then(results => setPlaylists(results.Items)) - .catch(() => setPlaylists([])); - // Artists row - fetchArtists(apiClient) - .then(result => setArtists(result.Items)) - .catch(() => setArtists([])); - // Albums row - fetchItems(apiClient, { IncludeItemTypes: 'MusicAlbum' }) - .then(result => setAlbums(result.Items)) - .catch(() => setAlbums([])); - // Songs row - fetchItems(apiClient, { IncludeItemTypes: 'Audio' }) - .then(result => setSongs(result.Items)) - .catch(() => setSongs([])); + fetchPromises.push( + // Playlists row + fetchItems(apiClient, { IncludeItemTypes: 'Playlist' }) + .then(results => setPlaylists(results.Items)) + .catch(() => setPlaylists([])), + // Artists row + fetchArtists(apiClient) + .then(result => setArtists(result.Items)) + .catch(() => setArtists([])), + // Albums row + fetchItems(apiClient, { IncludeItemTypes: 'MusicAlbum' }) + .then(result => setAlbums(result.Items)) + .catch(() => setAlbums([])), + // Songs row + fetchItems(apiClient, { IncludeItemTypes: 'Audio' }) + .then(result => setSongs(result.Items)) + .catch(() => setSongs([])) + ); } // Other libraries do not support in-library search currently if (!collectionType) { - // Videos row - fetchItems(apiClient, { - MediaTypes: 'Video', - ExcludeItemTypes: 'Movie,Episode,TvChannel' - }) - .then(result => setVideos(result.Items)) - .catch(() => setVideos([])); - // Programs row - fetchItems(apiClient, { IncludeItemTypes: 'LiveTvProgram' }) - .then(result => setPrograms(result.Items)) - .catch(() => setPrograms([])); - // Channels row - fetchItems(apiClient, { IncludeItemTypes: 'TvChannel' }) - .then(result => setChannels(result.Items)) - .catch(() => setChannels([])); - // Photo Albums row - fetchItems(apiClient, { IncludeItemTypes: 'PhotoAlbum' }) - .then(result => setPhotoAlbums(result.Items)) - .catch(() => setPhotoAlbums([])); - // Photos row - fetchItems(apiClient, { IncludeItemTypes: 'Photo' }) - .then(result => setPhotos(result.Items)) - .catch(() => setPhotos([])); - // Audio Books row - fetchItems(apiClient, { IncludeItemTypes: 'AudioBook' }) - .then(result => setAudioBooks(result.Items)) - .catch(() => setAudioBooks([])); - // Books row - fetchItems(apiClient, { IncludeItemTypes: 'Book' }) - .then(result => setBooks(result.Items)) - .catch(() => setBooks([])); - // Collections row - fetchItems(apiClient, { IncludeItemTypes: 'BoxSet' }) - .then(result => setCollections(result.Items)) - .catch(() => setCollections([])); + fetchPromises.push( + // Videos row + fetchItems(apiClient, { + MediaTypes: 'Video', + ExcludeItemTypes: 'Movie,Episode,TvChannel' + }) + .then(result => setVideos(result.Items)) + .catch(() => setVideos([])), + // Programs row + fetchItems(apiClient, { IncludeItemTypes: 'LiveTvProgram' }) + .then(result => setPrograms(result.Items)) + .catch(() => setPrograms([])), + // Channels row + fetchItems(apiClient, { IncludeItemTypes: 'TvChannel' }) + .then(result => setChannels(result.Items)) + .catch(() => setChannels([])), + // Photo Albums row + fetchItems(apiClient, { IncludeItemTypes: 'PhotoAlbum' }) + .then(result => setPhotoAlbums(result.Items)) + .catch(() => setPhotoAlbums([])), + // Photos row + fetchItems(apiClient, { IncludeItemTypes: 'Photo' }) + .then(result => setPhotos(result.Items)) + .catch(() => setPhotos([])), + // Audio Books row + fetchItems(apiClient, { IncludeItemTypes: 'AudioBook' }) + .then(result => setAudioBooks(result.Items)) + .catch(() => setAudioBooks([])), + // Books row + fetchItems(apiClient, { IncludeItemTypes: 'Book' }) + .then(result => setBooks(result.Items)) + .catch(() => setBooks([])), + // Collections row + fetchItems(apiClient, { IncludeItemTypes: 'BoxSet' }) + .then(result => setCollections(result.Items)) + .catch(() => setCollections([])) + ); } + Promise.all(fetchPromises) + .then(() => { + setIsLoading(false); // Set loading to false when all fetch calls are done + }) + .catch((error) => { + console.error('An error occurred while fetching data:', error); + setIsLoading(false); // Set loading to false even if an error occurs + }); }, [collectionType, fetchArtists, fetchItems, fetchPeople, query, serverId]); + const allEmpty = [movies, shows, episodes, videos, programs, channels, playlists, artists, albums, songs, photoAlbums, photos, audioBooks, books, people, collections].every(arr => arr.length === 0); + return (
= ({ serverId = windo { 'hide': !query || collectionType === 'livetv' } )} > - - - - - - - - - - - - - - - - + {isLoading ? ( + + ) : ( + <> + + + + + + + + + + + + + + + + + + {allEmpty && query && !isLoading && ( +
{globalize.translate('SearchResultsEmpty', query)}
+ )} + + )} +
); }; diff --git a/src/components/search/searchfields.scss b/src/components/search/searchfields.scss index 08d8515c865..b93638bdf3f 100644 --- a/src/components/search/searchfields.scss +++ b/src/components/search/searchfields.scss @@ -9,3 +9,14 @@ font-size: 2em; align-self: flex-end; } + +.sorry-text { + font-size: 2em; + text-align: center; + font-family: inherit; + width: 100%; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} diff --git a/src/strings/en-us.json b/src/strings/en-us.json index ecaf4ce77c5..464521d2758 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1428,6 +1428,7 @@ "SearchForMissingMetadata": "Search for missing metadata", "SearchForSubtitles": "Search for Subtitles", "SearchResults": "Search Results", + "SearchResultsEmpty": "Sorry! No results found for \"{0}\"", "Season": "Season", "SecondarySubtitles": "Secondary Subtitles", "SelectAdminUsername": "Please select a username for the admin account.",