new features context to render features correctly on change
This commit is contained in:
		
							
								
								
									
										46
									
								
								src/App.tsx
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								src/App.tsx
									
									
									
									
									
								
							@@ -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>
 | 
			
		||||
 
 | 
			
		||||
@@ -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')
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,7 @@ interface state {
 | 
			
		||||
    wrongPWDInfo: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
    onSuccessLogin: () => void;
 | 
			
		||||
}
 | 
			
		||||
interface Props {}
 | 
			
		||||
 | 
			
		||||
class AuthenticationPage extends React.Component<Props, state> {
 | 
			
		||||
    constructor(props: Props) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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})}
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
 
 | 
			
		||||
@@ -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}>
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								src/utils/context/FeatureContext.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/utils/context/FeatureContext.tsx
									
									
									
									
									
										Normal 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>;
 | 
			
		||||
};
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user