* no unauthorized init
* more dynamic Preview element
This commit is contained in:
		
							
								
								
									
										14
									
								
								src/App.tsx
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/App.tsx
									
									
									
									
									
								
							@@ -9,7 +9,7 @@ import style from './App.module.css';
 | 
			
		||||
 | 
			
		||||
import SettingsPage from './pages/SettingsPage/SettingsPage';
 | 
			
		||||
import CategoryPage from './pages/CategoryPage/CategoryPage';
 | 
			
		||||
import {APINode, apiTokenValid, callApiUnsafe, refreshAPIToken} from './utils/Api';
 | 
			
		||||
import {APINode, apiTokenValid, callAPI, refreshAPIToken} from './utils/Api';
 | 
			
		||||
 | 
			
		||||
import {BrowserRouter as Router, NavLink, Route, Switch} from 'react-router-dom';
 | 
			
		||||
import Player from './pages/Player/Player';
 | 
			
		||||
@@ -75,7 +75,7 @@ class App extends React.Component<{}, state> {
 | 
			
		||||
 | 
			
		||||
    initialAPICall(): void {
 | 
			
		||||
        // this is the first api call so if it fails we know there is no connection to backend
 | 
			
		||||
        callApiUnsafe(APINode.Init, {action: 'loadInitialData'}, (result: SettingsTypes.initialApiCallData) => {
 | 
			
		||||
        callAPI(APINode.Settings, {action: 'loadInitialData'}, (result: SettingsTypes.initialApiCallData) => {
 | 
			
		||||
            // set theme
 | 
			
		||||
            GlobalInfos.enableDarkTheme(result.DarkMode);
 | 
			
		||||
 | 
			
		||||
@@ -99,7 +99,15 @@ class App extends React.Component<{}, state> {
 | 
			
		||||
 | 
			
		||||
        if (this.state.password === true) {
 | 
			
		||||
            // render authentication page if auth is neccessary
 | 
			
		||||
            return <AuthenticationPage onSuccessLogin={(): void => this.setState({password: false})} />;
 | 
			
		||||
            return (
 | 
			
		||||
                <AuthenticationPage
 | 
			
		||||
                    onSuccessLogin={(): void => {
 | 
			
		||||
                        this.setState({password: false});
 | 
			
		||||
                        // reinit general infos
 | 
			
		||||
                        this.initialAPICall();
 | 
			
		||||
                    }}
 | 
			
		||||
                />
 | 
			
		||||
            );
 | 
			
		||||
        } else if (this.state.password === false) {
 | 
			
		||||
            return (
 | 
			
		||||
                <Router>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@ interface Props<T> {
 | 
			
		||||
 | 
			
		||||
interface state<T> {
 | 
			
		||||
    loadeditems: T[];
 | 
			
		||||
    selectionnr: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -24,8 +23,7 @@ class DynamicContentContainer<T> extends React.Component<Props<T>, state<T>> {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            loadeditems: [],
 | 
			
		||||
            selectionnr: 0
 | 
			
		||||
            loadeditems: []
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -35,6 +33,22 @@ class DynamicContentContainer<T> extends React.Component<Props<T>, state<T>> {
 | 
			
		||||
        this.loadPreviewBlock(this.props.initialLoadNr ? this.props.initialLoadNr : 16);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidUpdate(prevProps: Props<T>): void {
 | 
			
		||||
        // when source props change force update!
 | 
			
		||||
        if (prevProps.data.length !== this.props.data.length) {
 | 
			
		||||
            this.clean();
 | 
			
		||||
            this.loadPreviewBlock(this.props.initialLoadNr ? this.props.initialLoadNr : 16);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * clear all elements rendered...
 | 
			
		||||
     */
 | 
			
		||||
    clean(): void {
 | 
			
		||||
        this.loadindex = 0;
 | 
			
		||||
        this.setState({loadeditems: []});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
        return (
 | 
			
		||||
            <div className={style.maincontent}>
 | 
			
		||||
 
 | 
			
		||||
@@ -3,17 +3,18 @@ import style from './Preview.module.css';
 | 
			
		||||
import {Spinner} from 'react-bootstrap';
 | 
			
		||||
import {Link} from 'react-router-dom';
 | 
			
		||||
import GlobalInfos from '../../utils/GlobalInfos';
 | 
			
		||||
import {APINode, callAPIPlain} from '../../utils/Api';
 | 
			
		||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
 | 
			
		||||
import {faPhotoVideo} from '@fortawesome/free-solid-svg-icons';
 | 
			
		||||
 | 
			
		||||
interface PreviewProps {
 | 
			
		||||
    name: string;
 | 
			
		||||
    movieId: number;
 | 
			
		||||
    picLoader: (callback: (pic: string) => void) => void;
 | 
			
		||||
    linkPath?: string;
 | 
			
		||||
    onClick?: () => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface PreviewState {
 | 
			
		||||
    previewpicture: string | null;
 | 
			
		||||
    picLoaded: boolean | null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -21,49 +22,61 @@ interface PreviewState {
 | 
			
		||||
 * floating side by side
 | 
			
		||||
 */
 | 
			
		||||
class Preview extends React.Component<PreviewProps, PreviewState> {
 | 
			
		||||
    // store the picture to display
 | 
			
		||||
    pic?: string;
 | 
			
		||||
 | 
			
		||||
    constructor(props: PreviewProps) {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            previewpicture: null
 | 
			
		||||
            picLoaded: null
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
        callAPIPlain(APINode.Video, {action: 'readThumbnail', movieid: this.props.movieId}, (result) => {
 | 
			
		||||
        this.props.picLoader((result) => {
 | 
			
		||||
            this.pic = result;
 | 
			
		||||
            this.setState({
 | 
			
		||||
                previewpicture: result
 | 
			
		||||
                picLoaded: result !== ''
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
        if (this.props.linkPath !== undefined) {
 | 
			
		||||
            return <Link to={this.props.linkPath}>{this.content()}</Link>;
 | 
			
		||||
        } else {
 | 
			
		||||
            return this.content();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    content(): JSX.Element {
 | 
			
		||||
        const themeStyle = GlobalInfos.getThemeStyle();
 | 
			
		||||
        return (
 | 
			
		||||
            <Link to={'/player/' + this.props.movieId}>
 | 
			
		||||
                <div className={style.videopreview + ' ' + themeStyle.secbackground + ' ' + themeStyle.preview}>
 | 
			
		||||
                    <div className={style.previewtitle + ' ' + themeStyle.lighttextcolor}>{this.props.name}</div>
 | 
			
		||||
                    <div className={style.previewpic}>
 | 
			
		||||
                        {this.state.previewpicture === '' ? (
 | 
			
		||||
                            <FontAwesomeIcon
 | 
			
		||||
                                style={{
 | 
			
		||||
                                    color: 'white',
 | 
			
		||||
                                    marginTop: '55px'
 | 
			
		||||
                                }}
 | 
			
		||||
                                icon={faPhotoVideo}
 | 
			
		||||
                                size='5x'
 | 
			
		||||
                            />
 | 
			
		||||
                        ) : this.state.previewpicture === null ? (
 | 
			
		||||
                            <span className={style.loadAnimation}>
 | 
			
		||||
                                <Spinner animation='border' />
 | 
			
		||||
                            </span>
 | 
			
		||||
                        ) : (
 | 
			
		||||
                            <img className={style.previewimage} src={this.state.previewpicture} alt='Pic loading.' />
 | 
			
		||||
                        )}
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className={style.previewbottom} />
 | 
			
		||||
            <div
 | 
			
		||||
                className={style.videopreview + ' ' + themeStyle.secbackground + ' ' + themeStyle.preview}
 | 
			
		||||
                onClick={this.props.onClick}>
 | 
			
		||||
                <div className={style.previewtitle + ' ' + themeStyle.lighttextcolor}>{this.props.name}</div>
 | 
			
		||||
                <div className={style.previewpic}>
 | 
			
		||||
                    {this.state.picLoaded === false ? (
 | 
			
		||||
                        <FontAwesomeIcon
 | 
			
		||||
                            style={{
 | 
			
		||||
                                color: 'white',
 | 
			
		||||
                                marginTop: '55px'
 | 
			
		||||
                            }}
 | 
			
		||||
                            icon={faPhotoVideo}
 | 
			
		||||
                            size='5x'
 | 
			
		||||
                        />
 | 
			
		||||
                    ) : this.state.picLoaded === null ? (
 | 
			
		||||
                        <span className={style.loadAnimation}>
 | 
			
		||||
                            <Spinner animation='border' />
 | 
			
		||||
                        </span>
 | 
			
		||||
                    ) : (
 | 
			
		||||
                        <img className={style.previewimage} src={this.pic} alt='Pic loading.' />
 | 
			
		||||
                    )}
 | 
			
		||||
                </div>
 | 
			
		||||
            </Link>
 | 
			
		||||
                <div className={style.previewbottom} />
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ import React from 'react';
 | 
			
		||||
import Preview from '../Preview/Preview';
 | 
			
		||||
import {VideoTypes} from '../../types/ApiTypes';
 | 
			
		||||
import DynamicContentContainer from '../DynamicContentContainer/DynamicContentContainer';
 | 
			
		||||
import {APINode, callAPIPlain} from '../../utils/Api';
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
    data: VideoTypes.VideoUnloadedType[];
 | 
			
		||||
@@ -11,7 +12,23 @@ interface Props {
 | 
			
		||||
const VideoContainer = (props: Props): JSX.Element => {
 | 
			
		||||
    return (
 | 
			
		||||
        <DynamicContentContainer
 | 
			
		||||
            renderElement={(el): JSX.Element => <Preview key={el.MovieId} name={el.MovieName} movieId={el.MovieId} />}
 | 
			
		||||
            renderElement={(el): JSX.Element => (
 | 
			
		||||
                <Preview
 | 
			
		||||
                    key={el.MovieId}
 | 
			
		||||
                    picLoader={(callback: (pic: string) => void): void => {
 | 
			
		||||
                        callAPIPlain(
 | 
			
		||||
                            APINode.Video,
 | 
			
		||||
                            {
 | 
			
		||||
                                action: 'readThumbnail',
 | 
			
		||||
                                movieid: el.MovieId
 | 
			
		||||
                            },
 | 
			
		||||
                            (result) => callback(result)
 | 
			
		||||
                        );
 | 
			
		||||
                    }}
 | 
			
		||||
                    name={el.MovieName}
 | 
			
		||||
                    linkPath={'/player/' + el.MovieId}
 | 
			
		||||
                />
 | 
			
		||||
            )}
 | 
			
		||||
            data={props.data}>
 | 
			
		||||
            {props.children}
 | 
			
		||||
        </DynamicContentContainer>
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,10 @@ import {ActorType} from '../../types/VideoTypes';
 | 
			
		||||
import ActorTile from '../../elements/ActorTile/ActorTile';
 | 
			
		||||
import PageTitle from '../../elements/PageTitle/PageTitle';
 | 
			
		||||
import SideBar from '../../elements/SideBar/SideBar';
 | 
			
		||||
import style from './ActorOverviewPage.module.css';
 | 
			
		||||
// import style from './ActorOverviewPage.module.css';
 | 
			
		||||
import {Button} from '../../elements/GPElements/Button';
 | 
			
		||||
import NewActorPopup from '../../elements/Popups/NewActorPopup/NewActorPopup';
 | 
			
		||||
import DynamicContentContainer from '../../elements/DynamicContentContainer/DynamicContentContainer';
 | 
			
		||||
 | 
			
		||||
interface Props {}
 | 
			
		||||
 | 
			
		||||
@@ -36,11 +37,12 @@ class ActorOverviewPage extends React.Component<Props, state> {
 | 
			
		||||
                <SideBar>
 | 
			
		||||
                    <Button title='Add Actor' onClick={(): void => this.setState({NActorPopupVisible: true})} />
 | 
			
		||||
                </SideBar>
 | 
			
		||||
                <div className={style.container}>
 | 
			
		||||
                    {this.state.actors.map((el) => (
 | 
			
		||||
                        <ActorTile key={el.ActorId} actor={el} />
 | 
			
		||||
                    ))}
 | 
			
		||||
                </div>
 | 
			
		||||
                <DynamicContentContainer
 | 
			
		||||
                    renderElement={(el): JSX.Element => <ActorTile key={el.ActorId} actor={el} />}
 | 
			
		||||
                    data={this.state.actors}
 | 
			
		||||
                    initialLoadNr={36}
 | 
			
		||||
                />
 | 
			
		||||
 | 
			
		||||
                {this.state.NActorPopupVisible ? (
 | 
			
		||||
                    <NewActorPopup
 | 
			
		||||
                        onHide={(): void => {
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,7 @@ export class ActorPage extends React.Component<Props, state> {
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <SideBarTitle>Attention: This is an early preview!</SideBarTitle>
 | 
			
		||||
                </SideBar>
 | 
			
		||||
                {this.state.data.length !== 0 ? <VideoContainer data={this.state.data} /> : <div>No Data found!</div>}
 | 
			
		||||
                <VideoContainer data={this.state.data} />
 | 
			
		||||
            </>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -53,19 +53,15 @@ class TagView extends React.Component<Props, TagViewState> {
 | 
			
		||||
                        Add a new Tag!
 | 
			
		||||
                    </button>
 | 
			
		||||
                </SideBar>
 | 
			
		||||
                {this.state.loadedtags.length !== 0 ? (
 | 
			
		||||
                    <DynamicContentContainer
 | 
			
		||||
                        data={this.state.loadedtags}
 | 
			
		||||
                        renderElement={(m): JSX.Element => (
 | 
			
		||||
                            <Link to={'/categories/' + m.TagId} key={m.TagId}>
 | 
			
		||||
                                <TagPreview name={m.TagName} />
 | 
			
		||||
                            </Link>
 | 
			
		||||
                        )}
 | 
			
		||||
                        initialLoadNr={20}
 | 
			
		||||
                    />
 | 
			
		||||
                ) : (
 | 
			
		||||
                    'loading'
 | 
			
		||||
                )}
 | 
			
		||||
                <DynamicContentContainer
 | 
			
		||||
                    data={this.state.loadedtags}
 | 
			
		||||
                    renderElement={(m): JSX.Element => (
 | 
			
		||||
                        <Link to={'/categories/' + m.TagId} key={m.TagId}>
 | 
			
		||||
                            <TagPreview name={m.TagName} />
 | 
			
		||||
                        </Link>
 | 
			
		||||
                    )}
 | 
			
		||||
                    initialLoadNr={20}
 | 
			
		||||
                />
 | 
			
		||||
                {this.handlePopups()}
 | 
			
		||||
            </>
 | 
			
		||||
        );
 | 
			
		||||
 
 | 
			
		||||
@@ -157,7 +157,7 @@ export class HomePage extends React.Component<Props, state> {
 | 
			
		||||
                                }}
 | 
			
		||||
                            />
 | 
			
		||||
                        </SideBar>
 | 
			
		||||
                        {this.state.data.length !== 0 ? <VideoContainer data={this.state.data} /> : <div>No Data found!</div>}
 | 
			
		||||
                        <VideoContainer data={this.state.data} />
 | 
			
		||||
                        <div className={style.rightinfo} />
 | 
			
		||||
                    </Route>
 | 
			
		||||
                </Switch>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,13 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import Preview from '../../elements/Preview/Preview';
 | 
			
		||||
 | 
			
		||||
class TVShowPage extends React.Component {
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
        return <>TvShowPage</>;
 | 
			
		||||
        return (
 | 
			
		||||
            <>
 | 
			
		||||
                <Preview name='myTestItem' picLoader={(callback): void => callback('')} />
 | 
			
		||||
            </>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -279,6 +279,5 @@ export enum APINode {
 | 
			
		||||
    Settings = 'settings',
 | 
			
		||||
    Tags = 'tags',
 | 
			
		||||
    Actor = 'actor',
 | 
			
		||||
    Video = 'video',
 | 
			
		||||
    Init = 'init'
 | 
			
		||||
    Video = 'video'
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user