add a new TVPlayer component,
add tv episode path to db
This commit is contained in:
		@@ -40,4 +40,36 @@ func AddTvshowHandlers() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		return jsonify(episodes)
 | 
							return jsonify(episodes)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var le struct {
 | 
				
			||||||
 | 
							ID uint32
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						AddHandler("loadEpisode", TVShowNode, &le, func() []byte {
 | 
				
			||||||
 | 
							query := fmt.Sprintf(`
 | 
				
			||||||
 | 
					SELECT tvshow_episodes.name, season, tvshow_id, episode, filename, t.foldername
 | 
				
			||||||
 | 
					FROM tvshow_episodes 
 | 
				
			||||||
 | 
					JOIN tvshow t on t.id = tvshow_episodes.tvshow_id
 | 
				
			||||||
 | 
					WHERE tvshow_episodes.id=%d`, le.ID)
 | 
				
			||||||
 | 
							row := database.QueryRow(query)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var ret struct {
 | 
				
			||||||
 | 
								Name     string
 | 
				
			||||||
 | 
								Season   uint8
 | 
				
			||||||
 | 
								Episode  uint8
 | 
				
			||||||
 | 
								TVShowID uint32
 | 
				
			||||||
 | 
								Path     string
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var filename string
 | 
				
			||||||
 | 
							var foldername string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err := row.Scan(&ret.Name, &ret.Season, &ret.TVShowID, &ret.Episode, &filename, &foldername)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ret.Path = foldername + "/" + filename
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return jsonify(ret)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,8 +67,8 @@ func insertEpisode(path string, ShowName string) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	query := fmt.Sprintf(`
 | 
						query := fmt.Sprintf(`
 | 
				
			||||||
INSERT INTO tvshow_episodes (name, season, poster, tvshow_id, episode)
 | 
					INSERT INTO tvshow_episodes (name, season, poster, tvshow_id, episode, filename)
 | 
				
			||||||
VALUES ('%s', %d, '%s', (SELECT tvshow.id FROM tvshow WHERE tvshow.name='%s'), %d)`, name, season, "", ShowName, episode)
 | 
					VALUES ('%s', %d, '%s', (SELECT tvshow.id FROM tvshow WHERE tvshow.name='%s'), %d, '%s')`, name, season, "", ShowName, episode, path)
 | 
				
			||||||
	err = database.Edit(query)
 | 
						err = database.Edit(query)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		fmt.Println(err.Error())
 | 
							fmt.Println(err.Error())
 | 
				
			||||||
@@ -100,7 +100,8 @@ func insertShowIfNotExisting(show Show, allShows *[]string) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// todo load tmdb pic
 | 
						// todo load tmdb pic
 | 
				
			||||||
	query := fmt.Sprintf("INSERT INTO tvshow (name, thumbnail) VALUES ('%s', '%s')", show.Name, "")
 | 
						// currently the foldernamme == name which mustn't necessarily be
 | 
				
			||||||
 | 
						query := fmt.Sprintf("INSERT INTO tvshow (name, thumbnail, foldername) VALUES ('%s', '%s', '%s')", show.Name, "", show.Name)
 | 
				
			||||||
	err := database.Edit(query)
 | 
						err := database.Edit(query)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		fmt.Println(err.Error())
 | 
							fmt.Println(err.Error())
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								database.sql
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								database.sql
									
									
									
									
									
								
							@@ -11,8 +11,8 @@ create table if not exists settings
 | 
				
			|||||||
(
 | 
					(
 | 
				
			||||||
    video_path       varchar(255)                          null,
 | 
					    video_path       varchar(255)                          null,
 | 
				
			||||||
    episode_path     varchar(255)                          null,
 | 
					    episode_path     varchar(255)                          null,
 | 
				
			||||||
    password         varchar(32)       null,
 | 
					    password         varchar(32) default '-1'              null,
 | 
				
			||||||
    mediacenter_name varchar(32)       null,
 | 
					    mediacenter_name varchar(32) default 'OpenMediaCenter' null,
 | 
				
			||||||
    TMDB_grabbing    tinyint                               null,
 | 
					    TMDB_grabbing    tinyint                               null,
 | 
				
			||||||
    DarkMode         tinyint     default 0                 null
 | 
					    DarkMode         tinyint     default 0                 null
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
@@ -29,7 +29,8 @@ create table if not exists tvshow
 | 
				
			|||||||
    name       varchar(100) null,
 | 
					    name       varchar(100) null,
 | 
				
			||||||
    thumbnail  mediumblob   null,
 | 
					    thumbnail  mediumblob   null,
 | 
				
			||||||
    id         int auto_increment
 | 
					    id         int auto_increment
 | 
				
			||||||
        primary key
 | 
					        primary key,
 | 
				
			||||||
 | 
					    foldername varchar(100) null
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
create table if not exists tvshow_episodes
 | 
					create table if not exists tvshow_episodes
 | 
				
			||||||
@@ -40,6 +41,8 @@ create table if not exists tvshow_episodes
 | 
				
			|||||||
    season    int          null,
 | 
					    season    int          null,
 | 
				
			||||||
    poster    mediumblob   null,
 | 
					    poster    mediumblob   null,
 | 
				
			||||||
    tvshow_id int          null,
 | 
					    tvshow_id int          null,
 | 
				
			||||||
 | 
					    episode   int          null,
 | 
				
			||||||
 | 
					    filename  varchar(100) null,
 | 
				
			||||||
    constraint tvshow_episodes_tvshow_id_fk
 | 
					    constraint tvshow_episodes_tvshow_id_fk
 | 
				
			||||||
        foreign key (tvshow_id) references tvshow (id)
 | 
					        foreign key (tvshow_id) references tvshow (id)
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
@@ -51,11 +54,11 @@ create table if not exists videos
 | 
				
			|||||||
    movie_name  varchar(200)                         null,
 | 
					    movie_name  varchar(200)                         null,
 | 
				
			||||||
    movie_url   varchar(250)                         null,
 | 
					    movie_url   varchar(250)                         null,
 | 
				
			||||||
    thumbnail   mediumblob                           null,
 | 
					    thumbnail   mediumblob                           null,
 | 
				
			||||||
 | 
					    poster      mediumblob                           null,
 | 
				
			||||||
    likes       int      default 0                   null,
 | 
					    likes       int      default 0                   null,
 | 
				
			||||||
    create_date datetime default CURRENT_TIMESTAMP null,
 | 
					 | 
				
			||||||
    quality     int                                  null,
 | 
					    quality     int                                  null,
 | 
				
			||||||
    length      int                                  null comment 'in seconds',
 | 
					    length      int                                  null comment 'in seconds',
 | 
				
			||||||
    poster      mediumblob                         null
 | 
					    create_date datetime default current_timestamp() null
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
create table if not exists actors_videos
 | 
					create table if not exists actors_videos
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,7 @@ import ActorPage from './pages/ActorPage/ActorPage';
 | 
				
			|||||||
import {SettingsTypes} from './types/ApiTypes';
 | 
					import {SettingsTypes} from './types/ApiTypes';
 | 
				
			||||||
import AuthenticationPage from './pages/AuthenticationPage/AuthenticationPage';
 | 
					import AuthenticationPage from './pages/AuthenticationPage/AuthenticationPage';
 | 
				
			||||||
import TVShowPage from './pages/TVShowPage/TVShowPage';
 | 
					import TVShowPage from './pages/TVShowPage/TVShowPage';
 | 
				
			||||||
 | 
					import TVPlayer from './pages/TVShowPage/TVPlayer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface state {
 | 
					interface state {
 | 
				
			||||||
    password: boolean | null; // null if uninitialized - true if pwd needed false if not needed
 | 
					    password: boolean | null; // null if uninitialized - true if pwd needed false if not needed
 | 
				
			||||||
@@ -172,6 +173,9 @@ class App extends React.Component<{}, state> {
 | 
				
			|||||||
                <Route exact path='/player/:id'>
 | 
					                <Route exact path='/player/:id'>
 | 
				
			||||||
                    <Player />
 | 
					                    <Player />
 | 
				
			||||||
                </Route>
 | 
					                </Route>
 | 
				
			||||||
 | 
					                <Route exact path='/tvplayer/:id'>
 | 
				
			||||||
 | 
					                    <TVPlayer />
 | 
				
			||||||
 | 
					                </Route>
 | 
				
			||||||
                <Route exact path='/actors'>
 | 
					                <Route exact path='/actors'>
 | 
				
			||||||
                    <ActorOverviewPage />
 | 
					                    <ActorOverviewPage />
 | 
				
			||||||
                </Route>
 | 
					                </Route>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,14 +15,14 @@ import ActorTile from '../../elements/ActorTile/ActorTile';
 | 
				
			|||||||
import {withRouter} from 'react-router-dom';
 | 
					import {withRouter} from 'react-router-dom';
 | 
				
			||||||
import {APINode, callAPI} from '../../utils/Api';
 | 
					import {APINode, callAPI} from '../../utils/Api';
 | 
				
			||||||
import {RouteComponentProps} from 'react-router';
 | 
					import {RouteComponentProps} from 'react-router';
 | 
				
			||||||
import {GeneralSuccess} from '../../types/GeneralTypes';
 | 
					import {DefaultPlyrOptions, GeneralSuccess} from '../../types/GeneralTypes';
 | 
				
			||||||
import {ActorType, TagType} from '../../types/VideoTypes';
 | 
					import {ActorType, TagType} from '../../types/VideoTypes';
 | 
				
			||||||
import PlyrJS from 'plyr';
 | 
					import PlyrJS from 'plyr';
 | 
				
			||||||
import {Button} from '../../elements/GPElements/Button';
 | 
					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';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface myprops extends RouteComponentProps<{id: string}> {}
 | 
					interface Props extends RouteComponentProps<{id: string}> {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface mystate {
 | 
					interface mystate {
 | 
				
			||||||
    sources?: PlyrJS.SourceInfo;
 | 
					    sources?: PlyrJS.SourceInfo;
 | 
				
			||||||
@@ -42,25 +42,8 @@ interface mystate {
 | 
				
			|||||||
 * Player page loads when a video is selected to play and handles the video view
 | 
					 * Player page loads when a video is selected to play and handles the video view
 | 
				
			||||||
 * and actions such as tag adding and liking
 | 
					 * and actions such as tag adding and liking
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export class Player extends React.Component<myprops, mystate> {
 | 
					export class Player extends React.Component<Props, mystate> {
 | 
				
			||||||
    options: PlyrJS.Options = {
 | 
					    constructor(props: Props) {
 | 
				
			||||||
        controls: [
 | 
					 | 
				
			||||||
            'play-large', // The large play button in the center
 | 
					 | 
				
			||||||
            'play', // Play/pause playback
 | 
					 | 
				
			||||||
            'progress', // The progress bar and scrubber for playback and buffering
 | 
					 | 
				
			||||||
            'current-time', // The current time of playback
 | 
					 | 
				
			||||||
            'duration', // The full duration of the media
 | 
					 | 
				
			||||||
            'mute', // Toggle mute
 | 
					 | 
				
			||||||
            'volume', // Volume control
 | 
					 | 
				
			||||||
            'captions', // Toggle captions
 | 
					 | 
				
			||||||
            'settings', // Settings menu
 | 
					 | 
				
			||||||
            'airplay', // Airplay (currently Safari only)
 | 
					 | 
				
			||||||
            'download', // Show a download button with a link to either the current source or a custom URL you specify in your options
 | 
					 | 
				
			||||||
            'fullscreen' // Toggle fullscreen
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    constructor(props: myprops) {
 | 
					 | 
				
			||||||
        super(props);
 | 
					        super(props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.state = {
 | 
					        this.state = {
 | 
				
			||||||
@@ -94,7 +77,7 @@ export class Player extends React.Component<myprops, mystate> {
 | 
				
			|||||||
                <div className={style.videowrapper}>
 | 
					                <div className={style.videowrapper}>
 | 
				
			||||||
                    {/* video component is added here */}
 | 
					                    {/* video component is added here */}
 | 
				
			||||||
                    {this.state.sources ? (
 | 
					                    {this.state.sources ? (
 | 
				
			||||||
                        <Plyr style={plyrstyle} source={this.state.sources} options={this.options} />
 | 
					                        <Plyr style={plyrstyle} source={this.state.sources} options={DefaultPlyrOptions} />
 | 
				
			||||||
                    ) : (
 | 
					                    ) : (
 | 
				
			||||||
                        <div>not loaded yet</div>
 | 
					                        <div>not loaded yet</div>
 | 
				
			||||||
                    )}
 | 
					                    )}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										97
									
								
								src/pages/TVShowPage/TVPlayer.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/pages/TVShowPage/TVPlayer.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					import * as React from 'react';
 | 
				
			||||||
 | 
					import {RouteComponentProps} from 'react-router';
 | 
				
			||||||
 | 
					import {withRouter} from 'react-router-dom';
 | 
				
			||||||
 | 
					import PageTitle from '../../elements/PageTitle/PageTitle';
 | 
				
			||||||
 | 
					import style from '../Player/Player.module.css';
 | 
				
			||||||
 | 
					import {Plyr} from 'plyr-react';
 | 
				
			||||||
 | 
					import plyrstyle from 'plyr-react/dist/plyr.css';
 | 
				
			||||||
 | 
					import {DefaultPlyrOptions} from '../../types/GeneralTypes';
 | 
				
			||||||
 | 
					import {APINode, callAPI} from '../../utils/Api';
 | 
				
			||||||
 | 
					import GlobalInfos from '../../utils/GlobalInfos';
 | 
				
			||||||
 | 
					import PlyrJS from 'plyr';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Props extends RouteComponentProps<{id: string}> {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface State {
 | 
				
			||||||
 | 
					    loaded: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface EpisodeData {
 | 
				
			||||||
 | 
					    Name: string;
 | 
				
			||||||
 | 
					    Season: number;
 | 
				
			||||||
 | 
					    Episode: number;
 | 
				
			||||||
 | 
					    TVShowID: number;
 | 
				
			||||||
 | 
					    Path: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TVPlayer extends React.Component<Props, State> {
 | 
				
			||||||
 | 
					    state = {
 | 
				
			||||||
 | 
					        loaded: false
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data: EpisodeData | null = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    componentDidMount(): void {
 | 
				
			||||||
 | 
					        this.loadVideo();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    loadVideo(): void {
 | 
				
			||||||
 | 
					        callAPI(
 | 
				
			||||||
 | 
					            APINode.TVShow,
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                action: 'loadEpisode',
 | 
				
			||||||
 | 
					                ID: parseInt(this.props.match.params.id, 10)
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            (data: EpisodeData) => {
 | 
				
			||||||
 | 
					                console.log(data);
 | 
				
			||||||
 | 
					                this.data = data;
 | 
				
			||||||
 | 
					                this.setState({loaded: true});
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assemblePlyrObject(): JSX.Element {
 | 
				
			||||||
 | 
					        if (this.state.loaded && this.data !== null) {
 | 
				
			||||||
 | 
					            const sources: PlyrJS.SourceInfo = {
 | 
				
			||||||
 | 
					                type: 'video',
 | 
				
			||||||
 | 
					                sources: [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        src:
 | 
				
			||||||
 | 
					                            (process.env.REACT_APP_CUST_BACK_DOMAIN ? process.env.REACT_APP_CUST_BACK_DOMAIN : '') +
 | 
				
			||||||
 | 
					                            GlobalInfos.getTVShowPath() +
 | 
				
			||||||
 | 
					                            this.data.Path,
 | 
				
			||||||
 | 
					                        type: 'video/mp4',
 | 
				
			||||||
 | 
					                        size: 1080
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                poster: ''
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return <Plyr style={plyrstyle} source={sources} options={DefaultPlyrOptions} />;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return <div>not loaded yet</div>;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render(): JSX.Element {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <div id='videocontainer'>
 | 
				
			||||||
 | 
					                <PageTitle title='Watch' subtitle='todo' />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <div className={style.videowrapper}>
 | 
				
			||||||
 | 
					                    {/* video component is added here */}
 | 
				
			||||||
 | 
					                    {this.assemblePlyrObject()}
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <button className={style.closebutton} onClick={(): void => this.closebtn()}>
 | 
				
			||||||
 | 
					                    Close
 | 
				
			||||||
 | 
					                </button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private closebtn(): void {
 | 
				
			||||||
 | 
					        this.props.history.goBack();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default withRouter(TVPlayer);
 | 
				
			||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import {TagType} from './VideoTypes';
 | 
					import {TagType} from './VideoTypes';
 | 
				
			||||||
 | 
					import PlyrJS from 'plyr';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface GeneralSuccess {
 | 
					export interface GeneralSuccess {
 | 
				
			||||||
    result: string;
 | 
					    result: string;
 | 
				
			||||||
@@ -14,3 +15,20 @@ export const DefaultTags: TagarrayType = {
 | 
				
			|||||||
    lowq: {TagId: 3, TagName: 'lowquality'},
 | 
					    lowq: {TagId: 3, TagName: 'lowquality'},
 | 
				
			||||||
    hd: {TagId: 4, TagName: 'hd'}
 | 
					    hd: {TagId: 4, TagName: 'hd'}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const DefaultPlyrOptions: PlyrJS.Options = {
 | 
				
			||||||
 | 
					    controls: [
 | 
				
			||||||
 | 
					        'play-large', // The large play button in the center
 | 
				
			||||||
 | 
					        'play', // Play/pause playback
 | 
				
			||||||
 | 
					        'progress', // The progress bar and scrubber for playback and buffering
 | 
				
			||||||
 | 
					        'current-time', // The current time of playback
 | 
				
			||||||
 | 
					        'duration', // The full duration of the media
 | 
				
			||||||
 | 
					        'mute', // Toggle mute
 | 
				
			||||||
 | 
					        'volume', // Volume control
 | 
				
			||||||
 | 
					        'captions', // Toggle captions
 | 
				
			||||||
 | 
					        'settings', // Settings menu
 | 
				
			||||||
 | 
					        'airplay', // Airplay (currently Safari only)
 | 
				
			||||||
 | 
					        'download', // Show a download button with a link to either the current source or a custom URL you specify in your options
 | 
				
			||||||
 | 
					        'fullscreen' // Toggle fullscreen
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user