diff --git a/src/backend/metadata/getmeta.ts b/src/backend/metadata/getmeta.ts index fe2ea62b..c09d8292 100644 --- a/src/backend/metadata/getmeta.ts +++ b/src/backend/metadata/getmeta.ts @@ -201,29 +201,33 @@ export function decodeTMDBId( }; } +export function isLegacyUrl(url: string): boolean { + if (url.startsWith("/media/JW")) return true; + return false; +} + export async function convertLegacyUrl( url: string ): Promise<string | undefined> { - if (url.startsWith("/media/JW")) { - const urlParts = url.split("/").slice(2); - const [, type, id] = urlParts[0].split("-", 3); + if (!isLegacyUrl(url)) return undefined; - const mediaType = TMDBMediaToMediaType(type); - const meta = await getLegacyMetaFromId(mediaType, id); + const urlParts = url.split("/").slice(2); + const [, type, id] = urlParts[0].split("-", 3); - if (!meta) return undefined; - const { tmdbId, imdbId } = meta; - if (!tmdbId && !imdbId) return undefined; + const mediaType = TMDBMediaToMediaType(type); + const meta = await getLegacyMetaFromId(mediaType, id); - // movies always have an imdb id on tmdb - if (imdbId && mediaType === MWMediaType.MOVIE) { - const movieId = await getMovieFromExternalId(imdbId); - if (movieId) return `/media/tmdb-movie-${movieId}`; - } + if (!meta) return undefined; + const { tmdbId, imdbId } = meta; + if (!tmdbId && !imdbId) return undefined; - if (tmdbId) { - return `/media/tmdb-${type}-${tmdbId}`; - } + // movies always have an imdb id on tmdb + if (imdbId && mediaType === MWMediaType.MOVIE) { + const movieId = await getMovieFromExternalId(imdbId); + if (movieId) return `/media/tmdb-movie-${movieId}`; + } + + if (tmdbId) { + return `/media/tmdb-${type}-${tmdbId}`; } - return undefined; } diff --git a/src/setup/App.tsx b/src/setup/App.tsx index 0516eb48..7d1847ae 100644 --- a/src/setup/App.tsx +++ b/src/setup/App.tsx @@ -1,7 +1,13 @@ -import { lazy, useEffect, useState } from "react"; -import { Redirect, Route, Switch, useLocation } from "react-router-dom"; +import { ReactElement, lazy, useEffect } from "react"; +import { + Redirect, + Route, + Switch, + useHistory, + useLocation, +} from "react-router-dom"; -import { convertLegacyUrl } from "@/backend/metadata/getmeta"; +import { convertLegacyUrl, isLegacyUrl } from "@/backend/metadata/getmeta"; import { MWMediaType } from "@/backend/metadata/types/mw"; import { BannerContextProvider } from "@/hooks/useBanner"; import { Layout } from "@/setup/Layout"; @@ -13,27 +19,21 @@ import { NotFoundPage } from "@/views/notfound/NotFoundView"; import { V2MigrationView } from "@/views/other/v2Migration"; import { SearchView } from "@/views/search/SearchView"; -// eslint-disable-next-line react/function-component-definition, react/prop-types -const LegacyUrlView: React.FC = ({ children }) => { +function LegacyUrlView({ children }: { children: ReactElement }) { const location = useLocation(); - const [redirectUrl, setRedirectUrl] = useState<string | null>(null); + const { replace } = useHistory(); useEffect(() => { - // Call the conversion function and set the redirect URL if necessary + const url = location.pathname; + if (!isLegacyUrl(url)) return; convertLegacyUrl(location.pathname).then((convertedUrl) => { - if (convertedUrl) { - setRedirectUrl(convertedUrl); - } + replace(convertedUrl ?? "/"); }); - }, [location.pathname]); + }, [location.pathname, replace]); - if (redirectUrl) { - return <Redirect to={redirectUrl} />; - } - - // eslint-disable-next-line react/jsx-no-useless-fragment - return <>{children}</>; -}; + if (isLegacyUrl(location.pathname)) return null; + return children; +} function App() { return ( @@ -42,76 +42,74 @@ function App() { <BookmarkContextProvider> <BannerContextProvider> <Layout> - <LegacyUrlView> - <Switch> - {/* functional routes */} - <Route - exact - path="/v2-migration" - component={V2MigrationView} - /> - <Route exact path="/"> - <Redirect to={`/search/${MWMediaType.MOVIE}`} /> - </Route> + <Switch> + {/* functional routes */} + <Route exact path="/v2-migration" component={V2MigrationView} /> + <Route exact path="/"> + <Redirect to={`/search/${MWMediaType.MOVIE}`} /> + </Route> - {/* pages */} - <Route exact path="/media/:media" component={MediaView} /> - <Route - exact - path="/media/:media/:season/:episode" - component={MediaView} - /> - <Route - exact - path="/search/:type/:query?" - component={SearchView} - /> + {/* pages */} + <Route exact path="/media/:media"> + <LegacyUrlView> + <MediaView /> + </LegacyUrlView> + </Route> + <Route exact path="/media/:media/:season/:episode"> + <LegacyUrlView> + <MediaView /> + </LegacyUrlView> + </Route> + <Route + exact + path="/search/:type/:query?" + component={SearchView} + /> - {/* other */} - <Route - exact - path="/dev" - component={lazy( - () => import("@/views/developer/DeveloperView") - )} - /> - <Route - exact - path="/dev/video" - component={lazy( - () => import("@/views/developer/VideoTesterView") - )} - /> - {/* developer routes that can abuse workers are disabled in production */} - {process.env.NODE_ENV === "development" ? ( - <> - <Route - exact - path="/dev/test" - component={lazy( - () => import("@/views/developer/TestView") - )} - /> + {/* other */} + <Route + exact + path="/dev" + component={lazy( + () => import("@/views/developer/DeveloperView") + )} + /> + <Route + exact + path="/dev/video" + component={lazy( + () => import("@/views/developer/VideoTesterView") + )} + /> + {/* developer routes that can abuse workers are disabled in production */} + {process.env.NODE_ENV === "development" ? ( + <> + <Route + exact + path="/dev/test" + component={lazy( + () => import("@/views/developer/TestView") + )} + /> - <Route - exact - path="/dev/providers" - component={lazy( - () => import("@/views/developer/ProviderTesterView") - )} - /> - <Route - exact - path="/dev/embeds" - component={lazy( - () => import("@/views/developer/EmbedTesterView") - )} - /> - </> - ) : null} - <Route path="*" component={NotFoundPage} /> - </Switch> - </LegacyUrlView> + <Route + exact + path="/dev/providers" + component={lazy( + () => import("@/views/developer/ProviderTesterView") + )} + /> + <Route + exact + path="/dev/embeds" + component={lazy( + () => import("@/views/developer/EmbedTesterView") + )} + /> + </> + ) : null} + <Route path="*" component={NotFoundPage} /> + </Switch> </Layout> </BannerContextProvider> </BookmarkContextProvider>