diff --git a/.vscode/settings.json b/.vscode/settings.json index df15c3b2..490d5da2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "files.eol": "\n", "editor.detectIndentation": false, - "editor.formatOnSave": false, + "editor.formatOnSave": true, "editor.tabSize": 2 } \ No newline at end of file diff --git a/README.md b/README.md index 99ea4dbe..1f6e2679 100644 --- a/README.md +++ b/README.md @@ -39,17 +39,18 @@ Check out [this project's issues](https://github.com/JamesHawkinss/movie-web/iss - [x] Add results list end - [x] Store watched percentage - [x] Add Brand tag top left -- [X] Add github and discord top right +- [x] Add github and discord top right - [x] Link Github and Discord in error boundary - [ ] Implement movie + series view - - [ ] Global state for media objects - - [ ] Styling for pages + - [x] Global state for media objects + - [x] Styling for pages + - [ ] loading video player view + error - [ ] Series episodes+seasons -- [ ] On back button, persist the search query and results -- [ ] Bookmarking -- [ ] Resume from where you left of -- [ ] Less spaghett video player view -- [ ] Homepage continue watching + bookmarks +- [x] On back button, persist the search query and results +- [x] Bookmarking +- [x] Resume from where you left of +- [ ] Less spaghett video player view (implement source that are not mp4) +- [x] Homepage continue watching + bookmarks - [x] Add provider stream method - [x] Better looking error boundary - [x] sort search results so they aren't sorted by provider @@ -57,10 +58,13 @@ Check out [this project's issues](https://github.com/JamesHawkinss/movie-web/iss - [ ] Migrate old video progress - [ ] Get rid of react warnings - [ ] Implement more scrapers -- [ ] Add 404 page for media (media not found, provider disabled, provider not found) & general (page not found) +- [ ] Add 404 page for media (media not found, provider disabled, provider not found) & general (page not found) <--- +- [x] Change text of "thats all we have" ## Todo's after rewrite - [ ] Less spaghetti versioned storage (typesafe and works functionally) +- [ ] Add a way to remove from continue watching +- [ ] i18n - [ ] better mobile search type selector - [ ] Custom video player diff --git a/src/App.tsx b/src/App.tsx index 0ef231ba..baa949cd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,22 +1,24 @@ import { MWMediaType } from "providers"; import { Redirect, Route, Switch } from "react-router-dom"; -import { WatchedContextProvider } from "state/watched/context"; +import { BookmarkContextProvider } from "state/bookmark"; +import { WatchedContextProvider } from "state/watched"; import "./index.css"; -import { MovieView } from "./views/MovieView"; +import { MediaView } from "./views/MediaView"; import { SearchView } from "./views/SearchView"; -import { SeriesView } from "./views/SeriesView"; function App() { return ( - - - - - - - - + + + + + + + + + + ); } diff --git a/src/components/Text/DotList.tsx b/src/components/Text/DotList.tsx new file mode 100644 index 00000000..dc7b4dcd --- /dev/null +++ b/src/components/Text/DotList.tsx @@ -0,0 +1,19 @@ +export interface DotListProps { + content: string[]; + className?: string; +} + +export function DotList(props: DotListProps) { + return ( +

+ {props.content.map((item, index) => ( + + {index !== 0 ? ( + + ) : null} + {item} + + ))} +

+ ); +} diff --git a/src/components/layout/BrandPill.tsx b/src/components/layout/BrandPill.tsx index e71c3f92..d51e5104 100644 --- a/src/components/layout/BrandPill.tsx +++ b/src/components/layout/BrandPill.tsx @@ -5,7 +5,7 @@ export function BrandPill() { return (
- Movie Web + movie-web
) } diff --git a/src/components/layout/Loading.tsx b/src/components/layout/Loading.tsx index e12da6e2..14fab31e 100644 --- a/src/components/layout/Loading.tsx +++ b/src/components/layout/Loading.tsx @@ -6,7 +6,7 @@ export interface LoadingProps { export function Loading(props: LoadingProps) { return (
-
+
diff --git a/src/components/layout/Navigation.tsx b/src/components/layout/Navigation.tsx index af30be98..375878e6 100644 --- a/src/components/layout/Navigation.tsx +++ b/src/components/layout/Navigation.tsx @@ -1,13 +1,24 @@ import { IconPatch } from "components/buttons/IconPatch"; import { Icons } from "components/Icon"; import { DISCORD_LINK, GITHUB_LINK } from "mw_constants"; +import { ReactNode } from "react"; +import { Link } from "react-router-dom" import { BrandPill } from "./BrandPill"; -export function Navigation() { +export interface NavigationProps { + children?: ReactNode; +} + +export function Navigation(props: NavigationProps) { return (
-
- +
+
+ + + +
+ {props.children}
diff --git a/src/components/layout/Paper.tsx b/src/components/layout/Paper.tsx new file mode 100644 index 00000000..8659e97f --- /dev/null +++ b/src/components/layout/Paper.tsx @@ -0,0 +1,14 @@ +import { ReactNode } from "react"; + +export interface PaperProps { + children?: ReactNode, + className?: string, +} + +export function Paper(props: PaperProps) { + return ( +
+ {props.children} +
+ ) +} diff --git a/src/components/layout/SectionHeading.tsx b/src/components/layout/SectionHeading.tsx index d9f3c6aa..e341496b 100644 --- a/src/components/layout/SectionHeading.tsx +++ b/src/components/layout/SectionHeading.tsx @@ -8,11 +8,12 @@ interface SectionHeadingProps { children?: ReactNode; linkText?: string; onClick?: () => void; + className?: string; } export function SectionHeading(props: SectionHeadingProps) { return ( -
+

{props.icon ? ( diff --git a/src/components/media/EpisodeButton.tsx b/src/components/media/EpisodeButton.tsx new file mode 100644 index 00000000..1c5eccea --- /dev/null +++ b/src/components/media/EpisodeButton.tsx @@ -0,0 +1,18 @@ +export interface EpisodeProps { + progress?: number; + episodeNumber: number; +} + +export function Episode(props: EpisodeProps) { + return ( +

+
+ {props.episodeNumber} +
+ ); +} diff --git a/src/components/media/MediaCard.tsx b/src/components/media/MediaCard.tsx index 95d1a49d..41eb2ff5 100644 --- a/src/components/media/MediaCard.tsx +++ b/src/components/media/MediaCard.tsx @@ -1,38 +1,20 @@ import { convertMediaToPortable, getProviderFromId, - MWMedia, + MWMediaMeta, MWMediaType, } from "providers"; import { Link } from "react-router-dom"; import { Icon, Icons } from "components/Icon"; import { serializePortableMedia } from "hooks/usePortableMedia"; +import { DotList } from "components/text/DotList"; export interface MediaCardProps { - media: MWMedia; + media: MWMediaMeta; watchedPercentage: Number; linkable?: boolean; } -export interface MediaMetaProps { - content: string[]; -} - -function MediaMeta(props: MediaMetaProps) { - return ( -

- {props.content.map((item, index) => ( - - {index !== 0 ? ( - - ) : null} - {item} - - ))} -

- ); -} - function MediaCardContent({ media, linkable, @@ -68,7 +50,8 @@ function MediaCardContent({ {/* card content */}

{media.title}

-
diff --git a/src/components/media/VideoPlayer.tsx b/src/components/media/VideoPlayer.tsx index 17fa94ec..8784f3ed 100644 --- a/src/components/media/VideoPlayer.tsx +++ b/src/components/media/VideoPlayer.tsx @@ -1,22 +1,48 @@ +import { IconPatch } from "components/buttons/IconPatch"; +import { Icons } from "components/Icon"; +import { Loading } from "components/layout/Loading"; import { MWMediaStream } from "providers"; import { useRef } from "react"; export interface VideoPlayerProps { source: MWMediaStream; + startAt?: number; onProgress?: (event: ProgressEvent) => void; } +export function SkeletonVideoPlayer(props: { error?: boolean }) { + return ( +
+ {props.error ? ( +
+ +

Couldn't get your stream

+
+ ) : ( +
+ +

Getting your stream...

+
+ )} +
+ ); +} + export function VideoPlayer(props: VideoPlayerProps) { const videoRef = useRef(null); const mustUseHls = props.source.type === "m3u8"; return (
{/* results view */} @@ -162,8 +162,46 @@ export function SearchView() { searchQuery={debouncedSearch} clear={() => setSearch({ searchQuery: "" })} /> - ) : null} + ) : ( + + )} ); } + +function ExtraItems() { + const { bookmarkStore } = useBookmarkContext(); + const { watched } = useWatchedContext(); + const watchedItems = watched.items.filter( + (v) => !getIfBookmarkedFromPortable(bookmarkStore, v) + ); + + if (watchedItems.length === 0 && bookmarkStore.bookmarks.length === 0) + return null; + + return ( +
+ {bookmarkStore.bookmarks.length > 0 ? ( + + {bookmarkStore.bookmarks.map((v) => ( + + ))} + + ) : null} + {watchedItems.length > 0 ? ( + + {watchedItems.map((v) => ( + + ))} + + ) : null} +
+ ); +} diff --git a/src/views/SeriesView.tsx b/src/views/SeriesView.tsx deleted file mode 100644 index f535ca0f..00000000 --- a/src/views/SeriesView.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export function SeriesView() { - return ( -
-

Series view here

-
- ) -}