global persistent reactive storage 🎉

This commit is contained in:
Jelle van Snik 2022-02-18 21:11:23 +01:00
parent d217c4d9f4
commit 63742a1b60
6 changed files with 104 additions and 18 deletions

View File

@ -1,16 +1,19 @@
import { Route, Switch } from 'react-router-dom'; import { Route, Switch } from "react-router-dom";
import './index.css'; import { WatchedContextProvider } from "state/watched/context";
import { MovieView } from './views/MovieView'; import "./index.css";
import { SearchView } from './views/SearchView'; import { MovieView } from "./views/MovieView";
import { SeriesView } from './views/SeriesView'; import { SearchView } from "./views/SearchView";
import { SeriesView } from "./views/SeriesView";
function App() { function App() {
return ( return (
<Switch> <WatchedContextProvider>
<Route exact path="/" component={SearchView} /> <Switch>
<Route exact path="/media/movie" component={MovieView} /> <Route exact path="/" component={SearchView} />
<Route exact path="/media/series" component={SeriesView} /> <Route exact path="/media/movie" component={MovieView} />
</Switch> <Route exact path="/media/series" component={SeriesView} />
</Switch>
</WatchedContextProvider>
); );
} }

View File

@ -1,4 +1,5 @@
import { MWMedia } from "providers"; import { MWMedia } from "providers";
import { useWatchedContext, getWatchedFromPortable } from "state/watched";
import { MediaCard } from "./MediaCard"; import { MediaCard } from "./MediaCard";
export interface WatchedMediaCardProps { export interface WatchedMediaCardProps {
@ -6,5 +7,15 @@ export interface WatchedMediaCardProps {
} }
export function WatchedMediaCard(props: WatchedMediaCardProps) { export function WatchedMediaCard(props: WatchedMediaCardProps) {
return <MediaCard watchedPercentage={0} media={props.media} linkable />; const { watched } = useWatchedContext();
const foundWatched = getWatchedFromPortable(watched, props.media);
const watchedPercentage = (foundWatched && foundWatched.percentage) || 0;
return (
<MediaCard
watchedPercentage={watchedPercentage}
media={props.media}
linkable
/>
);
} }

View File

@ -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<React.SetStateAction<WatchedStoreData>>;
watched: WatchedStoreData;
}
const WatchedContext = createContext<WatchedStoreDataWrapper>({
setWatched: () => {},
watched: {
items: [],
},
});
WatchedContext.displayName = "WatchedContext";
export function WatchedContextProvider(props: { children: ReactNode }) {
const watchedLocalstorage = VideoProgressStore.get();
const [watched, setWatched] = useState<WatchedStoreData>(
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 (
<WatchedContext.Provider value={contextValue}>
{props.children}
</WatchedContext.Provider>
);
}
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
);
});
}

View File

@ -0,0 +1 @@
export * from "./context";

View File

@ -36,15 +36,16 @@ export const VideoProgressStore = versionedStoreBuilder()
.setKey('video-progress') .setKey('video-progress')
.addVersion({ .addVersion({
version: 0, version: 0,
migrate(data: any) {
// TODO migration
throw new Error("Migration not been written yet!!")
},
}) })
.addVersion({ .addVersion({
version: 1, version: 1,
migrate(data: any) {
// TODO migration
},
create() { create() {
return {} return {
items: [],
}
} }
}) })
.build() .build()

View File

@ -85,8 +85,9 @@ function buildStoreObject(d: any) {
data = this.update(data); data = this.update(data);
// add a save object to return value // add a save object to return value
data.save = function save() { data.save = function save(newData: any) {
localStorage.setItem(store.id, JSON.stringify(data)); let dataToStore = newData || data;
localStorage.setItem(store.id, JSON.stringify(dataToStore));
}; };
// add instance helpers // add instance helpers