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

View File

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

View File

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

View File

@ -22,6 +22,7 @@ import {Button} from '../../elements/GPElements/Button';
import {VideoTypes} from '../../types/ApiTypes'; import {VideoTypes} from '../../types/ApiTypes';
import GlobalInfos from '../../utils/GlobalInfos'; import GlobalInfos from '../../utils/GlobalInfos';
import {ButtonPopup} from '../../elements/Popups/ButtonPopup/ButtonPopup'; import {ButtonPopup} from '../../elements/Popups/ButtonPopup/ButtonPopup';
import {FeatureContext} from '../../utils/context/FeatureContext';
interface Props extends RouteComponentProps<{id: string}> {} interface Props extends RouteComponentProps<{id: string}> {}
@ -65,6 +66,8 @@ export class Player extends React.Component<Props, mystate> {
this.quickAddTag = this.quickAddTag.bind(this); this.quickAddTag = this.quickAddTag.bind(this);
} }
static contextType = FeatureContext;
componentDidMount(): void { componentDidMount(): void {
// initial fetch of current movie data // initial fetch of current movie data
this.fetchMovieData(); this.fetchMovieData();
@ -205,7 +208,7 @@ export class Player extends React.Component<Props, mystate> {
} }
renderDeletePopup(): JSX.Element { renderDeletePopup(): JSX.Element {
if (GlobalInfos.isVideoFulldeleteable()) { if (this.context.VideosFullyDeleteable) {
return ( return (
<ButtonPopup <ButtonPopup
onDeny={(): void => this.setState({deletepopupvisible: false})} 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 MovieSettings from './MovieSettings';
import GeneralSettings from './GeneralSettings'; import GeneralSettings from './GeneralSettings';
import style from './SettingsPage.module.css'; import style from './SettingsPage.module.css';
import GlobalInfos from '../../utils/GlobalInfos'; import GlobalInfos from '../../utils/GlobalInfos';
import {NavLink, Redirect, Route, Switch, useRouteMatch} from 'react-router-dom'; 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 * 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 SettingsPage = (): JSX.Element => {
const themestyle = GlobalInfos.getThemeStyle(); const themestyle = GlobalInfos.getThemeStyle();
const match = useRouteMatch(); const match = useRouteMatch();
const features = useContext(FeatureContext);
return ( return (
<div> <div>
@ -23,7 +25,7 @@ const SettingsPage = (): JSX.Element => {
<NavLink to='/media/settings/movies'> <NavLink to='/media/settings/movies'>
<div className={style.SettingSidebarElement}>Movies</div> <div className={style.SettingSidebarElement}>Movies</div>
</NavLink> </NavLink>
{GlobalInfos.isTVShowEnabled() ? ( {features.TVShowEnabled ? (
<NavLink to='/media/settings/tv'> <NavLink to='/media/settings/tv'>
<div className={style.SettingSidebarElement}>TV Shows</div> <div className={style.SettingSidebarElement}>TV Shows</div>
</NavLink> </NavLink>
@ -37,7 +39,7 @@ const SettingsPage = (): JSX.Element => {
<Route path={`${match.url}/movies`}> <Route path={`${match.url}/movies`}>
<MovieSettings /> <MovieSettings />
</Route> </Route>
{GlobalInfos.isTVShowEnabled() ? ( {features.TVShowEnabled ? (
<Route path={`${match.url}/tv`}> <Route path={`${match.url}/tv`}>
<span /> <span />
</Route> </Route>

View File

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

View File

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

View File

@ -49,6 +49,7 @@ class StaticInfos {
/** /**
* set the current videopath * set the current videopath
* @param vidpath videopath with beginning and ending slash * @param vidpath videopath with beginning and ending slash
* @param tvshowpath
*/ */
setVideoPaths(vidpath: string, tvshowpath: string): void { setVideoPaths(vidpath: string, tvshowpath: string): void {
this.videopath = vidpath; this.videopath = vidpath;
@ -68,27 +69,6 @@ class StaticInfos {
getTVShowPath(): string { getTVShowPath(): string {
return this.tvshowpath; 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(); 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 {APINode, callAPI} from '../Api';
import {SettingsTypes} from '../../types/ApiTypes'; import {SettingsTypes} from '../../types/ApiTypes';
import GlobalInfos from '../GlobalInfos'; import GlobalInfos from '../GlobalInfos';
import {FeatureContext} from './FeatureContext';
export const LoginContextProvider: FunctionComponent = (props): JSX.Element => { export const LoginContextProvider: FunctionComponent = (props): JSX.Element => {
let initialLoginState = LoginState.LoggedIn; let initialLoginState = LoginState.LoggedIn;
let initialUserPerm = LoginPerm.User; let initialUserPerm = LoginPerm.User;
const features = useContext(FeatureContext);
const t = cookie.Load(); const t = cookie.Load();
// we are already logged in so we can set the token and redirect to dashboard // we are already logged in so we can set the token and redirect to dashboard
if (t !== null) { if (t !== null) {
initialLoginState = LoginState.LoggedIn; 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 // this is the first api call so if it fails we know there is no connection to backend
callAPI( callAPI(
APINode.Settings, APINode.Settings,
@ -27,9 +30,9 @@ export const LoginContextProvider: FunctionComponent = (props): JSX.Element => {
GlobalInfos.setVideoPaths(result.VideoPath, result.TVShowPath); GlobalInfos.setVideoPaths(result.VideoPath, result.TVShowPath);
GlobalInfos.setTVShowsEnabled(result.TVShowEnabled); features.setTVShowEnabled(result.TVShowEnabled);
GlobalInfos.setFullDeleteEnabled(result.FullDeleteEnabled); features.setVideosFullyDeleteable(result.FullDeleteEnabled);
//
// this.setState({ // this.setState({
// mediacentername: result.MediacenterName // mediacentername: result.MediacenterName
// }); // });
@ -42,11 +45,7 @@ export const LoginContextProvider: FunctionComponent = (props): JSX.Element => {
setLoginState(LoginState.LoggedOut); setLoginState(LoginState.LoggedOut);
} }
); );
}; }, [features]);
useEffect(() => {
initialAPICall();
}, []);
const [loginState, setLoginState] = useState<LoginState>(initialLoginState); const [loginState, setLoginState] = useState<LoginState>(initialLoginState);
const [permission, setPermission] = useState<LoginPerm>(initialUserPerm); const [permission, setPermission] = useState<LoginPerm>(initialUserPerm);