mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-29 16:07:40 +01:00
global persistent reactive storage 🎉
This commit is contained in:
parent
d217c4d9f4
commit
63742a1b60
6 changed files with 104 additions and 18 deletions
23
src/App.tsx
23
src/App.tsx
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
69
src/state/watched/context.tsx
Normal file
69
src/state/watched/context.tsx
Normal 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
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
1
src/state/watched/index.ts
Normal file
1
src/state/watched/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from "./context";
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue