1
0
Fork 0
mirror of https://github.com/sussy-code/smov.git synced 2025-01-01 16:37:39 +01:00

404 pages for all cases

This commit is contained in:
mrjvs 2022-03-06 12:56:22 +01:00
parent 356b9af4ff
commit 8a42364a95
8 changed files with 75 additions and 30 deletions

View file

@ -57,13 +57,13 @@ Check out [this project's issues](https://github.com/JamesHawkinss/movie-web/iss
- [x] video load error, video loading (from actual video player) - [x] video load error, video loading (from actual video player)
- [ ] Series episodes+seasons - [ ] Series episodes+seasons
- [ ] Get rid of react warnings - [ ] Get rid of react warnings
- [ ] Add 404 page for media (media not found, provider disabled, provider not found) & general (page not found) - [x] Add 404 page for media (media not found, provider disabled, provider not found) & general (page not found)
- [ ] Handle disabled providers (continue watching, bookmarks & router) - [x] Handle disabled providers (continue watching, bookmarks & router)
- [ ] Subtitles - [ ] Subtitles
- [ ] Implement all scrapers - [ ] Implement all scrapers
- [ ] implement sources that are not mp4 - [ ] implement sources that are not mp4
- [x] Bug: go back doesn't work if used directly from link
- [ ] Migrate old video progress - [ ] Migrate old video progress
- [ ] Bug: go back doesn't work if used directly from link
## After all rewrite code has been written ## After all rewrite code has been written

View file

@ -2,7 +2,7 @@ import { MWMediaType } from "providers";
import { Redirect, Route, Switch } from "react-router-dom"; import { Redirect, Route, Switch } from "react-router-dom";
import { BookmarkContextProvider } from "state/bookmark"; import { BookmarkContextProvider } from "state/bookmark";
import { WatchedContextProvider } from "state/watched"; import { WatchedContextProvider } from "state/watched";
import { NotFoundPage } from "views/NotFoundView"; import { NotFoundPage } from "views/notfound/NotFoundView";
import "./index.css"; import "./index.css";
import { MediaView } from "./views/MediaView"; import { MediaView } from "./views/MediaView";
import { SearchView } from "./views/SearchView"; import { SearchView } from "./views/SearchView";

View file

@ -8,7 +8,7 @@ export interface WatchedMediaCardProps {
export function WatchedMediaCard(props: WatchedMediaCardProps) { export function WatchedMediaCard(props: WatchedMediaCardProps) {
const { watched } = useWatchedContext(); const { watched } = useWatchedContext();
const foundWatched = getWatchedFromPortable(watched, props.media); const foundWatched = getWatchedFromPortable(watched.items, props.media);
const watchedPercentage = (foundWatched && foundWatched.percentage) || 0; const watchedPercentage = (foundWatched && foundWatched.percentage) || 0;
return ( return (

View file

@ -1,4 +1,4 @@
import { MWMediaMeta } from "providers"; import { MWMediaMeta, getProviderMetadata } from "providers";
import React, { createContext, ReactNode, useContext, useState } from "react"; import React, { createContext, ReactNode, useContext, useState } from "react";
import { VideoProgressStore } from "./store"; import { VideoProgressStore } from "./store";
@ -13,11 +13,13 @@ interface WatchedStoreData {
interface WatchedStoreDataWrapper { interface WatchedStoreDataWrapper {
updateProgress(media: MWMediaMeta, progress: number, total: number): void; updateProgress(media: MWMediaMeta, progress: number, total: number): void;
getFilteredWatched(): WatchedStoreItem[];
watched: WatchedStoreData; watched: WatchedStoreData;
} }
const WatchedContext = createContext<WatchedStoreDataWrapper>({ const WatchedContext = createContext<WatchedStoreDataWrapper>({
updateProgress: () => {}, updateProgress: () => {},
getFilteredWatched: () => [],
watched: { watched: {
items: [], items: [],
}, },
@ -42,13 +44,9 @@ export function WatchedContextProvider(props: { children: ReactNode }) {
} }
const contextValue = { const contextValue = {
updateProgress( updateProgress(media: MWMediaMeta, progress: number, total: number): void {
media: MWMediaMeta,
progress: number,
total: number
): void {
setWatched((data: WatchedStoreData) => { setWatched((data: WatchedStoreData) => {
let item = getWatchedFromPortable(data, media); let item = getWatchedFromPortable(data.items, media);
if (!item) { if (!item) {
item = { item = {
mediaId: media.mediaId, mediaId: media.mediaId,
@ -71,6 +69,11 @@ export function WatchedContextProvider(props: { children: ReactNode }) {
return data; return data;
}); });
}, },
getFilteredWatched() {
return watched.items.filter((item) => {
return getProviderMetadata(item.providerId)?.enabled;
});
},
watched, watched,
}; };
@ -86,10 +89,10 @@ export function useWatchedContext() {
} }
export function getWatchedFromPortable( export function getWatchedFromPortable(
store: WatchedStoreData, items: WatchedStoreItem[],
media: MWMediaMeta media: MWMediaMeta
): WatchedStoreItem | undefined { ): WatchedStoreItem | undefined {
return store.items.find((v) => { return items.find((v) => {
return ( return (
v.mediaId === media.mediaId && v.mediaId === media.mediaId &&
v.providerId === media.providerId && v.providerId === media.providerId &&

View file

@ -18,11 +18,13 @@ import {
MWMediaProvider, MWMediaProvider,
} from "providers"; } from "providers";
import { ReactNode, useEffect, useState } from "react"; import { ReactNode, useEffect, useState } from "react";
import { useHistory } from "react-router-dom";
import { import {
getIfBookmarkedFromPortable, getIfBookmarkedFromPortable,
useBookmarkContext, useBookmarkContext,
} from "state/bookmark"; } from "state/bookmark";
import { getWatchedFromPortable, useWatchedContext } from "state/watched"; import { getWatchedFromPortable, useWatchedContext } from "state/watched";
import { NotFoundChecks } from "./notfound/NotFoundChecks";
interface StyledMediaViewProps { interface StyledMediaViewProps {
media: MWMedia; media: MWMedia;
@ -31,9 +33,9 @@ interface StyledMediaViewProps {
} }
function StyledMediaView(props: StyledMediaViewProps) { function StyledMediaView(props: StyledMediaViewProps) {
const store = useWatchedContext(); const watchedStore = useWatchedContext();
const startAtTime: number | undefined = getWatchedFromPortable( const startAtTime: number | undefined = getWatchedFromPortable(
store.watched, watchedStore.watched.items,
props.media props.media
)?.progress; )?.progress;
const { setItemBookmark, getFilteredBookmarks } = useBookmarkContext(); const { setItemBookmark, getFilteredBookmarks } = useBookmarkContext();
@ -48,7 +50,7 @@ function StyledMediaView(props: StyledMediaViewProps) {
if (el.currentTime <= 30) { if (el.currentTime <= 30) {
return; // Don't update stored progress if less than 30s into the video return; // Don't update stored progress if less than 30s into the video
} }
store.updateProgress(props.media, el.currentTime, el.duration); watchedStore.updateProgress(props.media, el.currentTime, el.duration);
} }
return ( return (
@ -104,8 +106,8 @@ function LoadingMediaView(props: { error?: boolean }) {
); );
} }
export function MediaView() { function MediaViewContent(props: { portable: MWPortableMedia }) {
const mediaPortable: MWPortableMedia | undefined = usePortableMedia(); const mediaPortable = props.portable;
const [streamUrl, setStreamUrl] = useState<MWMediaStream | undefined>(); const [streamUrl, setStreamUrl] = useState<MWMediaStream | undefined>();
const [media, setMedia] = useState<MWMedia | undefined>(); const [media, setMedia] = useState<MWMedia | undefined>();
const [fetchAllData, loading, error] = useLoading((mediaPortable) => { const [fetchAllData, loading, error] = useLoading((mediaPortable) => {
@ -139,18 +141,31 @@ export function MediaView() {
/> />
); );
return <>{content}</>;
}
export function MediaView() {
const mediaPortable: MWPortableMedia | undefined = usePortableMedia();
const reactHistory = useHistory();
return ( return (
<div className="w-full"> <div className="flex min-h-screen w-full">
<Navigation> <Navigation>
<ArrowLink <ArrowLink
onClick={() => window.history.back()} onClick={() => {
reactHistory.action !== "POP"
? reactHistory.goBack()
: reactHistory.push("/");
}}
direction="left" direction="left"
linkText="Go back" linkText="Go back"
/> />
</Navigation> </Navigation>
<div className="container mx-auto mt-40 mb-16 max-w-[1100px]"> <NotFoundChecks portable={mediaPortable}>
{content} <div className="container mx-auto mt-40 mb-16 max-w-[1100px]">
</div> <MediaViewContent portable={mediaPortable as MWPortableMedia} />
</div>
</NotFoundChecks>
</div> </div>
); );
} }

View file

@ -172,11 +172,11 @@ export function SearchView() {
function ExtraItems() { function ExtraItems() {
const { getFilteredBookmarks } = useBookmarkContext(); const { getFilteredBookmarks } = useBookmarkContext();
const { watched } = useWatchedContext(); const { getFilteredWatched } = useWatchedContext();
const bookmarks = getFilteredBookmarks(); const bookmarks = getFilteredBookmarks();
const watchedItems = watched.items.filter( const watchedItems = getFilteredWatched().filter(
(v) => !getIfBookmarkedFromPortable(bookmarks, v) (v) => !getIfBookmarkedFromPortable(bookmarks, v)
); );

View file

@ -0,0 +1,27 @@
import { getProviderMetadata, MWPortableMedia } from "providers";
import { ReactNode } from "react";
import { NotFoundMedia, NotFoundProvider } from "./NotFoundView";
export interface NotFoundChecksProps {
portable: MWPortableMedia | undefined;
children?: ReactNode;
}
/*
** Component that only renders children if the passed-in portable is fully correct
*/
export function NotFoundChecks(props: NotFoundChecksProps) {
const providerMeta = props.portable
? getProviderMetadata(props.portable.providerId)
: undefined;
if (!providerMeta || !providerMeta.exists) {
return <NotFoundMedia />;
}
if (!providerMeta.enabled) {
return <NotFoundProvider />;
}
return <>{props.children}</>;
}

View file

@ -18,7 +18,7 @@ function NotFoundWrapper(props: { children?: ReactNode }) {
export function NotFoundMedia() { export function NotFoundMedia() {
return ( return (
<NotFoundWrapper> <div className="flex flex-1 flex-col items-center justify-center p-5 text-center">
<IconPatch <IconPatch
icon={Icons.EYE_SLASH} icon={Icons.EYE_SLASH}
className="text-bink-600 mb-6 text-xl" className="text-bink-600 mb-6 text-xl"
@ -29,13 +29,13 @@ export function NotFoundMedia() {
you tampered with the URL you tampered with the URL
</p> </p>
<ArrowLink to="/" linkText="Back to home" /> <ArrowLink to="/" linkText="Back to home" />
</NotFoundWrapper> </div>
); );
} }
export function NotFoundProvider() { export function NotFoundProvider() {
return ( return (
<NotFoundWrapper> <div className="flex flex-1 flex-col items-center justify-center p-5 text-center">
<IconPatch <IconPatch
icon={Icons.EYE_SLASH} icon={Icons.EYE_SLASH}
className="text-bink-600 mb-6 text-xl" className="text-bink-600 mb-6 text-xl"
@ -46,7 +46,7 @@ export function NotFoundProvider() {
to disable it. to disable it.
</p> </p>
<ArrowLink to="/" linkText="Back to home" /> <ArrowLink to="/" linkText="Back to home" />
</NotFoundWrapper> </div>
); );
} }