From 2ffead179a29fd291564531dc7d01ff175e71b1b Mon Sep 17 00:00:00 2001 From: Nathan G Date: Sun, 1 Oct 2023 17:44:39 -0700 Subject: [PATCH 1/4] First iteration --- jellyfin-web.code-workspace | 8 + src/components/search/SearchResults.tsx | 343 +++++++++++++----------- 2 files changed, 197 insertions(+), 154 deletions(-) create mode 100644 jellyfin-web.code-workspace diff --git a/jellyfin-web.code-workspace b/jellyfin-web.code-workspace new file mode 100644 index 00000000000..876a1499c09 --- /dev/null +++ b/jellyfin-web.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/src/components/search/SearchResults.tsx b/src/components/search/SearchResults.tsx index f8e5a12fbd1..bb0ca208473 100644 --- a/src/components/search/SearchResults.tsx +++ b/src/components/search/SearchResults.tsx @@ -45,6 +45,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, @@ -112,101 +113,124 @@ const SearchResults: FunctionComponent = ({ serverId = windo setBooks([]); setPeople([]); setCollections([]); + setIsLoading(true); if (!query) { + setIsLoading(false); return; } 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 ? ( +
Loading...
// Replace this with your preferred progress indicator + ) : ( + <> + + + + + + + + + + + + + + + + + + {allEmpty && !isLoading && ( +
Sorry, nothing's here :/
+ )} + + )} +
); }; From 838d496aab3f4f630115b7647c08398fa6ba92be Mon Sep 17 00:00:00 2001 From: Nathan G Date: Sun, 1 Oct 2023 18:16:19 -0700 Subject: [PATCH 2/4] Main Iteration --- src/components/search/SearchResults.tsx | 4 ++-- src/components/search/searchfields.scss | 31 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/components/search/SearchResults.tsx b/src/components/search/SearchResults.tsx index bb0ca208473..ae58bc9465f 100644 --- a/src/components/search/SearchResults.tsx +++ b/src/components/search/SearchResults.tsx @@ -241,7 +241,7 @@ const SearchResults: FunctionComponent = ({ serverId = windo )} > {isLoading ? ( -
Loading...
// Replace this with your preferred progress indicator +
) : ( <> = ({ serverId = windo /> {allEmpty && !isLoading && ( -
Sorry, nothing's here :/
+
Sorry! No results found for "{query}"
)} )} diff --git a/src/components/search/searchfields.scss b/src/components/search/searchfields.scss index 08d8515c865..4580dfcb802 100644 --- a/src/components/search/searchfields.scss +++ b/src/components/search/searchfields.scss @@ -9,3 +9,34 @@ 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%); +} + +// New styles for loading circle +.loading-circle { + border: 5px solid #557ece; + border-radius: 50%; + border-top: 5px solid #1b1b1bd7; + width: 65px; + height: 65px; + animation: spin 1s linear infinite; + margin: auto; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +@keyframes spin { + 0% { transform: translate(-50%, -50%) rotate(0deg); } + 100% { transform: translate(-50%, -50%) rotate(360deg); } +} From e615621d3b2d903d6534f60271a75b0b67dc5dda Mon Sep 17 00:00:00 2001 From: Nathan G Date: Sun, 1 Oct 2023 19:20:31 -0700 Subject: [PATCH 3/4] Delete jellyfin-web.code-workspace --- jellyfin-web.code-workspace | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 jellyfin-web.code-workspace diff --git a/jellyfin-web.code-workspace b/jellyfin-web.code-workspace deleted file mode 100644 index 876a1499c09..00000000000 --- a/jellyfin-web.code-workspace +++ /dev/null @@ -1,8 +0,0 @@ -{ - "folders": [ - { - "path": "." - } - ], - "settings": {} -} \ No newline at end of file From 4c486286a0ce0be48095222db93e0fef2f703d4e Mon Sep 17 00:00:00 2001 From: Nathan G Date: Sun, 1 Oct 2023 19:52:54 -0700 Subject: [PATCH 4/4] Update CONTRIBUTORS.md --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index eccfd4cf279..d935489893f 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -66,6 +66,7 @@ - [Fishbigger](https://github.com/fishbigger) - [sleepycatcoding](https://github.com/sleepycatcoding) - [TheMelmacian](https://github.com/TheMelmacian) + - [Nate G](https://github.com/GGProGaming) # Emby Contributors