From 63742a1b6024dfec30f530af7ac93fd92922eec6 Mon Sep 17 00:00:00 2001 From: Jelle van Snik Date: Fri, 18 Feb 2022 21:11:23 +0100 Subject: [PATCH] global persistent reactive storage :tada: --- src/App.tsx | 23 ++++---- src/components/media/WatchedMediaCard.tsx | 13 ++++- src/state/watched/context.tsx | 69 +++++++++++++++++++++++ src/state/watched/index.ts | 1 + src/state/watched/store.ts | 11 ++-- src/utils/storage.ts | 5 +- 6 files changed, 104 insertions(+), 18 deletions(-) create mode 100644 src/state/watched/context.tsx create mode 100644 src/state/watched/index.ts diff --git a/src/App.tsx b/src/App.tsx index aa7bf137..4f5a4cc4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,16 +1,19 @@ -import { Route, Switch } from 'react-router-dom'; -import './index.css'; -import { MovieView } from './views/MovieView'; -import { SearchView } from './views/SearchView'; -import { SeriesView } from './views/SeriesView'; +import { Route, Switch } from "react-router-dom"; +import { WatchedContextProvider } from "state/watched/context"; +import "./index.css"; +import { MovieView } from "./views/MovieView"; +import { SearchView } from "./views/SearchView"; +import { SeriesView } from "./views/SeriesView"; function App() { return ( - - - - - + + + + + + + ); } diff --git a/src/components/media/WatchedMediaCard.tsx b/src/components/media/WatchedMediaCard.tsx index eaa1de2b..a3fe8013 100644 --- a/src/components/media/WatchedMediaCard.tsx +++ b/src/components/media/WatchedMediaCard.tsx @@ -1,4 +1,5 @@ import { MWMedia } from "providers"; +import { useWatchedContext, getWatchedFromPortable } from "state/watched"; import { MediaCard } from "./MediaCard"; export interface WatchedMediaCardProps { @@ -6,5 +7,15 @@ export interface WatchedMediaCardProps { } export function WatchedMediaCard(props: WatchedMediaCardProps) { - return ; + const { watched } = useWatchedContext(); + const foundWatched = getWatchedFromPortable(watched, props.media); + const watchedPercentage = (foundWatched && foundWatched.percentage) || 0; + + return ( + + ); } diff --git a/src/state/watched/context.tsx b/src/state/watched/context.tsx new file mode 100644 index 00000000..c2e05a89 --- /dev/null +++ b/src/state/watched/context.tsx @@ -0,0 +1,69 @@ +import { MWPortableMedia } from "providers"; +import React, { createContext, ReactNode, useContext, useState } from "react"; +import { VideoProgressStore } from "./store"; + +interface WatchedStoreItem extends MWPortableMedia { + progress: number; + percentage: number; +} + +interface WatchedStoreData { + items: WatchedStoreItem[]; +} + +interface WatchedStoreDataWrapper { + setWatched: React.Dispatch>; + watched: WatchedStoreData; +} + +const WatchedContext = createContext({ + setWatched: () => {}, + watched: { + items: [], + }, +}); +WatchedContext.displayName = "WatchedContext"; + +export function WatchedContextProvider(props: { children: ReactNode }) { + const watchedLocalstorage = VideoProgressStore.get(); + const [watched, setWatched] = useState( + watchedLocalstorage as WatchedStoreData + ); + const contextValue = { + setWatched(data: any) { + setWatched((old) => { + let newData = data; + if (data.constructor === Function) { + newData = data(old); + } + watchedLocalstorage.save(newData); + return newData; + }); + }, + watched, + }; + + return ( + + {props.children} + + ); +} + +export function useWatchedContext() { + return useContext(WatchedContext); +} + +export function getWatchedFromPortable( + store: WatchedStoreData, + media: MWPortableMedia +): WatchedStoreItem | undefined { + return store.items.find((v) => { + return ( + v.mediaId === media.mediaId && + v.providerId === media.providerId && + v.episode === media.episode && + v.season === media.season + ); + }); +} diff --git a/src/state/watched/index.ts b/src/state/watched/index.ts new file mode 100644 index 00000000..2edd280c --- /dev/null +++ b/src/state/watched/index.ts @@ -0,0 +1 @@ +export * from "./context"; diff --git a/src/state/watched/store.ts b/src/state/watched/store.ts index 30380675..108c1c6f 100644 --- a/src/state/watched/store.ts +++ b/src/state/watched/store.ts @@ -36,15 +36,16 @@ export const VideoProgressStore = versionedStoreBuilder() .setKey('video-progress') .addVersion({ version: 0, - migrate(data: any) { - // TODO migration - throw new Error("Migration not been written yet!!") - }, }) .addVersion({ version: 1, + migrate(data: any) { + // TODO migration + }, create() { - return {} + return { + items: [], + } } }) .build() diff --git a/src/utils/storage.ts b/src/utils/storage.ts index add77d96..0ddb0e22 100644 --- a/src/utils/storage.ts +++ b/src/utils/storage.ts @@ -85,8 +85,9 @@ function buildStoreObject(d: any) { data = this.update(data); // add a save object to return value - data.save = function save() { - localStorage.setItem(store.id, JSON.stringify(data)); + data.save = function save(newData: any) { + let dataToStore = newData || data; + localStorage.setItem(store.id, JSON.stringify(dataToStore)); }; // add instance helpers