new features context to render features correctly on change

This commit is contained in:
lukas 2021-09-20 12:20:22 +02:00
parent f17bac399a
commit e71f262b79
10 changed files with 67 additions and 83 deletions

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, {useContext} from 'react';
import HomePage from './pages/HomePage/HomePage';
import RandomPage from './pages/RandomPage/RandomPage';
import GlobalInfos from './utils/GlobalInfos';
@ -18,6 +18,7 @@ import AuthenticationPage from './pages/AuthenticationPage/AuthenticationPage';
import TVShowPage from './pages/TVShowPage/TVShowPage';
import TVPlayer from './pages/TVShowPage/TVPlayer';
import {LoginContextProvider} from './utils/context/LoginContextProvider';
import {FeatureContext} from './utils/context/FeatureContext';
interface state {
mediacentername: string;
@ -48,13 +49,7 @@ class App extends React.Component<{}, state> {
<LoginContextProvider>
<Switch>
<Route path='/login'>
<AuthenticationPage
onSuccessLogin={(): void => {
// this.setState({password: false});
// reinit general infos
// this.initialAPICall();
}}
/>
<AuthenticationPage />
</Route>
<Route path='/media'>
{this.navBar()}
@ -63,32 +58,10 @@ class App extends React.Component<{}, state> {
</Switch>
</LoginContextProvider>
);
// if (this.state.password === true) {
// // render authentication page if auth is neccessary
// return (
// <AuthenticationPage
// onSuccessLogin={(): void => {
// this.setState({password: false});
// // reinit general infos
// this.initialAPICall();
// }}
// />
// );
// } else if (this.state.password === false) {
// return (
// <Router>
// <div className={style.app}>
// {this.navBar()}
// {this.routing()}
// </div>
// </Router>
// );
// } else {
// return <>still loading...</>;
// }
}
static contextType = FeatureContext;
/**
* render the top navigation bar
*/
@ -115,7 +88,7 @@ class App extends React.Component<{}, state> {
Categories
</NavLink>
{GlobalInfos.isTVShowEnabled() ? (
{this.context.TVShowEnabled ? (
<NavLink
className={[style.navitem, themeStyle.navitem].join(' ')}
to={'/media/tvshows'}
@ -137,6 +110,7 @@ class App extends React.Component<{}, state> {
const MyRouter = (): JSX.Element => {
const match = useRouteMatch();
const features = useContext(FeatureContext);
return (
<Switch>
@ -159,13 +133,13 @@ const MyRouter = (): JSX.Element => {
<ActorPage />
</Route>
{GlobalInfos.isTVShowEnabled() ? (
<Route exact path={`${match.url}/tvshows`}>
{features.TVShowEnabled ? (
<Route path={`${match.url}/tvshows`}>
<TVShowPage />
</Route>
) : null}
{GlobalInfos.isTVShowEnabled() ? (
{features.TVShowEnabled ? (
<Route exact path={`${match.url}/tvplayer/:id`}>
<TVPlayer />
</Route>

View File

@ -2,6 +2,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {BrowserRouter} from 'react-router-dom';
import {FeatureContextProvider} from './utils/context/FeatureContext';
// don't allow console logs within production env
global.console.log = process.env.NODE_ENV !== 'development' ? (_: string | number | boolean): void => {} : global.console.log;
@ -9,7 +10,9 @@ global.console.log = process.env.NODE_ENV !== 'development' ? (_: string | numbe
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
<FeatureContextProvider>
<App />
</FeatureContextProvider>
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')

View File

@ -13,9 +13,7 @@ interface state {
wrongPWDInfo: boolean;
}
interface Props {
onSuccessLogin: () => void;
}
interface Props {}
class AuthenticationPage extends React.Component<Props, state> {
constructor(props: Props) {

View File

@ -22,6 +22,7 @@ import {Button} from '../../elements/GPElements/Button';
import {VideoTypes} from '../../types/ApiTypes';
import GlobalInfos from '../../utils/GlobalInfos';
import {ButtonPopup} from '../../elements/Popups/ButtonPopup/ButtonPopup';
import {FeatureContext} from '../../utils/context/FeatureContext';
interface Props extends RouteComponentProps<{id: string}> {}
@ -65,6 +66,8 @@ export class Player extends React.Component<Props, mystate> {
this.quickAddTag = this.quickAddTag.bind(this);
}
static contextType = FeatureContext;
componentDidMount(): void {
// initial fetch of current movie data
this.fetchMovieData();
@ -205,7 +208,7 @@ export class Player extends React.Component<Props, mystate> {
}
renderDeletePopup(): JSX.Element {
if (GlobalInfos.isVideoFulldeleteable()) {
if (this.context.VideosFullyDeleteable) {
return (
<ButtonPopup
onDeny={(): void => this.setState({deletepopupvisible: false})}

View File

@ -1,9 +1,10 @@
import React from 'react';
import React, {useContext} from 'react';
import MovieSettings from './MovieSettings';
import GeneralSettings from './GeneralSettings';
import style from './SettingsPage.module.css';
import GlobalInfos from '../../utils/GlobalInfos';
import {NavLink, Redirect, Route, Switch, useRouteMatch} from 'react-router-dom';
import {FeatureContext} from '../../utils/context/FeatureContext';
/**
* The Settingspage handles all kinds of settings for the mediacenter
@ -12,6 +13,7 @@ import {NavLink, Redirect, Route, Switch, useRouteMatch} from 'react-router-dom'
const SettingsPage = (): JSX.Element => {
const themestyle = GlobalInfos.getThemeStyle();
const match = useRouteMatch();
const features = useContext(FeatureContext);
return (
<div>
@ -23,7 +25,7 @@ const SettingsPage = (): JSX.Element => {
<NavLink to='/media/settings/movies'>
<div className={style.SettingSidebarElement}>Movies</div>
</NavLink>
{GlobalInfos.isTVShowEnabled() ? (
{features.TVShowEnabled ? (
<NavLink to='/media/settings/tv'>
<div className={style.SettingSidebarElement}>TV Shows</div>
</NavLink>
@ -37,7 +39,7 @@ const SettingsPage = (): JSX.Element => {
<Route path={`${match.url}/movies`}>
<MovieSettings />
</Route>
{GlobalInfos.isTVShowEnabled() ? (
{features.TVShowEnabled ? (
<Route path={`${match.url}/tv`}>
<span />
</Route>

View File

@ -72,7 +72,7 @@ export default function (): JSX.Element {
return (
<Switch>
<Route path={`${match.path}/:id`}>
<Route exact path={`${match.path}/:id`}>
<EpisodePage />
</Route>
<Route path={match.path}>

View File

@ -1,4 +1,3 @@
import GlobalInfos from './GlobalInfos';
import {cookie} from './context/Cookie';
const APIPREFIX: string = '/api/';
@ -84,13 +83,7 @@ function generalAPICall<T>(
}
} else if (response.status === 400) {
// Bad Request --> invalid token
console.log('loading Password page.');
// load password page
if (GlobalInfos.loadPasswordPage) {
GlobalInfos.loadPasswordPage(() => {
callAPI(apinode, fd, callback, errorcallback);
});
}
console.log('bad request todo sth here');
} else {
console.log('Error: ' + response.statusText);
if (errorcallback) {

View File

@ -49,6 +49,7 @@ class StaticInfos {
/**
* set the current videopath
* @param vidpath videopath with beginning and ending slash
* @param tvshowpath
*/
setVideoPaths(vidpath: string, tvshowpath: string): void {
this.videopath = vidpath;
@ -68,27 +69,6 @@ class StaticInfos {
getTVShowPath(): string {
return this.tvshowpath;
}
/**
* load the Password page manually
*/
loadPasswordPage: ((callback?: () => void) => void) | undefined = undefined;
setTVShowsEnabled(TVShowEnabled: boolean): void {
this.TVShowsEnabled = TVShowEnabled;
}
isTVShowEnabled(): boolean {
return this.TVShowsEnabled;
}
setFullDeleteEnabled(FullDeleteEnabled: boolean): void {
this.fullDeleteable = FullDeleteEnabled;
}
isVideoFulldeleteable(): boolean {
return this.fullDeleteable;
}
}
export default new StaticInfos();

View File

@ -0,0 +1,32 @@
import React, {FunctionComponent, useState} from 'react';
export interface FeatureContextType {
setTVShowEnabled: (enabled: boolean) => void;
TVShowEnabled: boolean;
setVideosFullyDeleteable: (fullyDeletable: boolean) => void;
VideosFullyDeleteable: boolean;
}
/**
* A global context providing a way to interact with user login states
*/
export const FeatureContext = React.createContext<FeatureContextType>({
setTVShowEnabled: (_) => {},
TVShowEnabled: false,
setVideosFullyDeleteable: (_) => {},
VideosFullyDeleteable: false
});
export const FeatureContextProvider: FunctionComponent = (props): JSX.Element => {
const [tvshowenabled, settvshowenabled] = useState(false);
const [fullydeletablevids, setfullydeleteable] = useState(false);
const value: FeatureContextType = {
VideosFullyDeleteable: fullydeletablevids,
TVShowEnabled: tvshowenabled,
setTVShowEnabled: (e) => settvshowenabled(e),
setVideosFullyDeleteable: (e) => setfullydeleteable(e)
};
return <FeatureContext.Provider value={value}>{props.children}</FeatureContext.Provider>;
};

View File

@ -5,18 +5,21 @@ import {cookie} from './Cookie';
import {APINode, callAPI} from '../Api';
import {SettingsTypes} from '../../types/ApiTypes';
import GlobalInfos from '../GlobalInfos';
import {FeatureContext} from './FeatureContext';
export const LoginContextProvider: FunctionComponent = (props): JSX.Element => {
let initialLoginState = LoginState.LoggedIn;
let initialUserPerm = LoginPerm.User;
const features = useContext(FeatureContext);
const t = cookie.Load();
// we are already logged in so we can set the token and redirect to dashboard
if (t !== null) {
initialLoginState = LoginState.LoggedIn;
}
const initialAPICall = (): void => {
useEffect(() => {
// this is the first api call so if it fails we know there is no connection to backend
callAPI(
APINode.Settings,
@ -27,9 +30,9 @@ export const LoginContextProvider: FunctionComponent = (props): JSX.Element => {
GlobalInfos.setVideoPaths(result.VideoPath, result.TVShowPath);
GlobalInfos.setTVShowsEnabled(result.TVShowEnabled);
GlobalInfos.setFullDeleteEnabled(result.FullDeleteEnabled);
//
features.setTVShowEnabled(result.TVShowEnabled);
features.setVideosFullyDeleteable(result.FullDeleteEnabled);
// this.setState({
// mediacentername: result.MediacenterName
// });
@ -42,11 +45,7 @@ export const LoginContextProvider: FunctionComponent = (props): JSX.Element => {
setLoginState(LoginState.LoggedOut);
}
);
};
useEffect(() => {
initialAPICall();
}, []);
}, [features]);
const [loginState, setLoginState] = useState<LoginState>(initialLoginState);
const [permission, setPermission] = useState<LoginPerm>(initialUserPerm);