@@ -1,47 +0,0 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en" dir="ltr">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="utf-8">
 | 
			
		||||
    <title>hub</title>
 | 
			
		||||
    <link rel="stylesheet" href="css/plyr.css"/>
 | 
			
		||||
    <link rel="stylesheet" href="css/index.css">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <!-- Latest compiled and minified CSS -->
 | 
			
		||||
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
 | 
			
		||||
 | 
			
		||||
    <!-- jQuery library -->
 | 
			
		||||
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
 | 
			
		||||
 | 
			
		||||
    <!-- Popper JS -->
 | 
			
		||||
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
 | 
			
		||||
 | 
			
		||||
    <!-- Latest compiled JavaScript -->
 | 
			
		||||
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
 | 
			
		||||
 | 
			
		||||
    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@9"></script>
 | 
			
		||||
 | 
			
		||||
    <script src="js/plyr.js"></script>
 | 
			
		||||
    <script src="js/index.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<!-- Grey with black text -->
 | 
			
		||||
<nav class="navbar navbar-expand-sm bg-primary navbar-dark">
 | 
			
		||||
    <!-- Brand -->
 | 
			
		||||
    <a class="navbar-brand" href="#">Lukis Tube</a>
 | 
			
		||||
 | 
			
		||||
    <ul class="navbar-nav">
 | 
			
		||||
        <li class="nav-item ">
 | 
			
		||||
            <a class="nav-link" href="index.html">Home</a>
 | 
			
		||||
        </li>
 | 
			
		||||
        <li class="nav-item">
 | 
			
		||||
            <a class="nav-link" href="random.html">Random Video</a>
 | 
			
		||||
        </li>
 | 
			
		||||
        <li class="nav-item active">
 | 
			
		||||
            <a class="nav-link" href="category.html">Categories</a>
 | 
			
		||||
        </li>
 | 
			
		||||
    </ul>
 | 
			
		||||
</nav>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										86
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								index.html
									
									
									
									
									
								
							@@ -1,86 +0,0 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en" dir="ltr">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="utf-8">
 | 
			
		||||
    <title>hub</title>
 | 
			
		||||
    <link rel="stylesheet" href="css/plyr.css"/>
 | 
			
		||||
    <link rel="stylesheet" href="css/index.css">
 | 
			
		||||
    <link rel="stylesheet" href="css/video.css">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <!-- Latest compiled and minified CSS -->
 | 
			
		||||
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
 | 
			
		||||
 | 
			
		||||
    <!-- jQuery library -->
 | 
			
		||||
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
 | 
			
		||||
 | 
			
		||||
    <!-- Popper JS -->
 | 
			
		||||
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
 | 
			
		||||
 | 
			
		||||
    <!-- Latest compiled JavaScript -->
 | 
			
		||||
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
 | 
			
		||||
 | 
			
		||||
    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@9"></script>
 | 
			
		||||
 | 
			
		||||
    <script src="js/plyr.js"></script>
 | 
			
		||||
    <script src="js/index.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<!-- Grey with black text -->
 | 
			
		||||
<nav class="navbar navbar-expand-sm bg-primary navbar-dark">
 | 
			
		||||
    <!-- Brand -->
 | 
			
		||||
    <a class="navbar-brand" href="#">Lukis Tube</a>
 | 
			
		||||
 | 
			
		||||
    <ul class="navbar-nav">
 | 
			
		||||
        <li class="nav-item active">
 | 
			
		||||
            <a class="nav-link" href="index.html">Home</a>
 | 
			
		||||
        </li>
 | 
			
		||||
        <li class="nav-item">
 | 
			
		||||
            <a class="nav-link" href="random.html">Random Video</a>
 | 
			
		||||
        </li>
 | 
			
		||||
        <li class="nav-item">
 | 
			
		||||
            <a class="nav-link" href="category.html">Categories</a>
 | 
			
		||||
        </li>
 | 
			
		||||
    </ul>
 | 
			
		||||
</nav>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<div class="videopagewrapper hideit">
 | 
			
		||||
    <div class="row">
 | 
			
		||||
        <div class="col-sm-2">
 | 
			
		||||
            <div class="videoleftbanner">
 | 
			
		||||
                <div class="likefield">Likes: 10</div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-sm-8">
 | 
			
		||||
            <div class="videowrapper"></div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-sm-2">
 | 
			
		||||
            <div class="closebutton">Close</div>
 | 
			
		||||
            <div class="videorightbanner"></div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="row">
 | 
			
		||||
        <div class="col-sm-5">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-sm-2">
 | 
			
		||||
            <button id="likebtn">Like it!</button>
 | 
			
		||||
            <button id="tagbutton">Tag it!</button>
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-sm-5">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<div class="previewcontainer">
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										130
									
								
								js/index.js
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								js/index.js
									
									
									
									
									
								
							@@ -1,130 +0,0 @@
 | 
			
		||||
let videos;
 | 
			
		||||
let loadindex = 0;
 | 
			
		||||
let scrollposition = 0;
 | 
			
		||||
let loadedvideoid = -1;
 | 
			
		||||
 | 
			
		||||
$(document).ready(function () {
 | 
			
		||||
    $.post('php/videoload.php', 'action=getMovies', function (data) {
 | 
			
		||||
        videos = data;
 | 
			
		||||
        loadPreviewBlock(15);
 | 
			
		||||
    }, 'json');
 | 
			
		||||
 | 
			
		||||
    $.post('php/videoload.php', 'action=getDbSize', function (data) {
 | 
			
		||||
        console.log(data);
 | 
			
		||||
    }, 'json');
 | 
			
		||||
 | 
			
		||||
    $(".closebutton").click(function () {
 | 
			
		||||
        $("#likebtn").off();
 | 
			
		||||
        $("#tagbutton").off();
 | 
			
		||||
        $(".videopagewrapper").hide();
 | 
			
		||||
        $(".previewcontainer").show();
 | 
			
		||||
        // scroll back to last scroll position
 | 
			
		||||
        $(window).scrollTop(scrollposition);
 | 
			
		||||
        $(".videowrapper").html("");
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
$(window).scroll(function () {
 | 
			
		||||
    if ($(window).scrollTop() >= (($(document).height() - $(window).height() - 60))) {
 | 
			
		||||
        if ($(".videowrapper").html() === "") {
 | 
			
		||||
            loadPreviewBlock(6);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function loadPreviewBlock(nr) {
 | 
			
		||||
    for (let i = 0; i < nr; i++) {
 | 
			
		||||
        if (loadindex + i < videos.length) {
 | 
			
		||||
            loadPreview(videos[loadindex + i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    loadindex += nr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function loadPreview(src) {
 | 
			
		||||
    $.post('php/videoload.php', 'action=readThumbnail&movieid=' + src.movie_id, function (data) {
 | 
			
		||||
        var preview = $(`
 | 
			
		||||
<div class='videopreview'>
 | 
			
		||||
    <div class='previewtitle'>${src.movie_name}</div>
 | 
			
		||||
    <div class='previewpic'>
 | 
			
		||||
        <img style='width:100%;height:100%' src="${data}" alt='no thumbnail found'/>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>`);
 | 
			
		||||
        preview.attr('movie_id', src.movie_id);
 | 
			
		||||
        preview.click(function () {
 | 
			
		||||
            console.log("preview clicked");
 | 
			
		||||
            scrollposition = $(window).scrollTop();
 | 
			
		||||
            loadedvideoid = $(this).attr("movie_id");
 | 
			
		||||
            loadVideo(loadedvideoid);
 | 
			
		||||
        });
 | 
			
		||||
        $(".previewcontainer").append(preview);
 | 
			
		||||
    }, 'text');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function loadVideo(movieid) {
 | 
			
		||||
    $.post('php/videoload.php', 'action=loadVideo&movieid=' + movieid, function (data) {
 | 
			
		||||
        $(".videowrapper").html("<div class='myvideo'><video controls crossorigin playsinline id='player'></video></div>");
 | 
			
		||||
 | 
			
		||||
        const player = new Plyr('#player');
 | 
			
		||||
        player.source = {
 | 
			
		||||
            type: 'video',
 | 
			
		||||
            sources: [
 | 
			
		||||
                {
 | 
			
		||||
                    src: data.movie_url,
 | 
			
		||||
                    type: 'video/mp4',
 | 
			
		||||
                    size: 1080,
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            poster: data.thumbnail
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        $(".likefield").html("Likes: " + data.likes);
 | 
			
		||||
 | 
			
		||||
        $.post('php/videoload.php', 'action=getTags&movieid=' + loadedvideoid, function (data) {
 | 
			
		||||
            for (const tag in data.tags) {
 | 
			
		||||
                $(".videoleftbanner").append(`<div>${tag}</div>`);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            console.log(data);
 | 
			
		||||
        }, "json");
 | 
			
		||||
 | 
			
		||||
        $("#likebtn").click(function () {
 | 
			
		||||
            console.log("likebtn clicked");
 | 
			
		||||
            $.post('php/videoload.php', 'action=addLike&movieid=' + loadedvideoid, function (data) {
 | 
			
		||||
                console.log(data);
 | 
			
		||||
            }, "json");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        $("#tagbutton").click(function () {
 | 
			
		||||
            console.log("tagbrn clicked");
 | 
			
		||||
            Swal.mixin({
 | 
			
		||||
                input: 'text',
 | 
			
		||||
                confirmButtonText: 'Next →',
 | 
			
		||||
                showCancelButton: true,
 | 
			
		||||
                progressSteps: ['1', '2', '3']
 | 
			
		||||
            }).queue([
 | 
			
		||||
                {
 | 
			
		||||
                    title: 'Question 1',
 | 
			
		||||
                    text: 'Chaining swal2 modals is easy'
 | 
			
		||||
                },
 | 
			
		||||
                'Question 2',
 | 
			
		||||
                'Question 3'
 | 
			
		||||
            ]).then((result) => {
 | 
			
		||||
                if (result.value) {
 | 
			
		||||
                    const answers = JSON.stringify(result.value)
 | 
			
		||||
                    Swal.fire({
 | 
			
		||||
                        title: 'All done!',
 | 
			
		||||
                        html: `
 | 
			
		||||
        Your answers:
 | 
			
		||||
        <pre><code>${answers}</code></pre>
 | 
			
		||||
      `,
 | 
			
		||||
                        confirmButtonText: 'Lovely!'
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        $(".videopagewrapper").show();
 | 
			
		||||
        $(".previewcontainer").hide();
 | 
			
		||||
    }, "json");
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										125
									
								
								js/random.js
									
									
									
									
									
								
							
							
						
						
									
										125
									
								
								js/random.js
									
									
									
									
									
								
							@@ -1,125 +0,0 @@
 | 
			
		||||
let videos;
 | 
			
		||||
let loadindex = 0;
 | 
			
		||||
let loadedvideoid = -1;
 | 
			
		||||
 | 
			
		||||
$(document).ready(function () {
 | 
			
		||||
    $.post('php/videoload.php', 'action=getRandomMovies&number=6', function (data) {
 | 
			
		||||
        videos = data;
 | 
			
		||||
        loadPreviewBlock(6);
 | 
			
		||||
    }, 'json');
 | 
			
		||||
 | 
			
		||||
    $(".closebutton").click(function () {
 | 
			
		||||
        $("#likebtn").off();
 | 
			
		||||
        $("#tagbutton").off();
 | 
			
		||||
        $(".videopagewrapper").hide();
 | 
			
		||||
        $(".previewcontainer").show();
 | 
			
		||||
        // scroll back to last scroll position
 | 
			
		||||
        $(window).scrollTop(scrollposition);
 | 
			
		||||
        $(".videowrapper").html("");
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $("#shufflebtn").click(function () {
 | 
			
		||||
        $(".previewcontainer").html("");
 | 
			
		||||
        $.post('php/videoload.php', 'action=getRandomMovies&number=6', function (data) {
 | 
			
		||||
            videos = data;
 | 
			
		||||
            loadPreviewBlock(6);
 | 
			
		||||
        }, 'json');
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function loadPreviewBlock(nr) {
 | 
			
		||||
    for (let i = 0; i < nr; i++) {
 | 
			
		||||
        if (loadindex + i < videos.length) {
 | 
			
		||||
            loadPreview(videos[loadindex + i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    loadindex += nr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function loadPreview(src) {
 | 
			
		||||
    $.post('php/videoload.php', 'action=readThumbnail&movieid=' + src.movie_id, function (data) {
 | 
			
		||||
        var preview = $(`
 | 
			
		||||
<div class='videopreview'>
 | 
			
		||||
    <div class='previewtitle'>${src.movie_name}</div>
 | 
			
		||||
    <div class='previewpic'>
 | 
			
		||||
        <img style='width:100%;height:100%' src="${data}" alt='no thumbnail found'/>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>`);
 | 
			
		||||
        preview.attr('movie_id', src.movie_id);
 | 
			
		||||
        preview.click(function () {
 | 
			
		||||
            console.log("preview clicked");
 | 
			
		||||
            scrollposition = $(window).scrollTop();
 | 
			
		||||
            loadedvideoid = $(this).attr("movie_id");
 | 
			
		||||
            loadVideo(loadedvideoid);
 | 
			
		||||
        });
 | 
			
		||||
        $(".previewcontainer").append(preview);
 | 
			
		||||
    }, 'text');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function loadVideo(movieid) {
 | 
			
		||||
    $.post('php/videoload.php', 'action=loadVideo&movieid=' + movieid, function (data) {
 | 
			
		||||
        $(".videowrapper").html("<div class='myvideo'><video controls crossorigin playsinline id='player'></video></div>");
 | 
			
		||||
 | 
			
		||||
        const player = new Plyr('#player');
 | 
			
		||||
        player.source = {
 | 
			
		||||
            type: 'video',
 | 
			
		||||
            sources: [
 | 
			
		||||
                {
 | 
			
		||||
                    src: data.movie_url,
 | 
			
		||||
                    type: 'video/mp4',
 | 
			
		||||
                    size: 1080,
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            poster: data.thumbnail
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        $(".likefield").html("Likes: " + data.likes);
 | 
			
		||||
 | 
			
		||||
        $.post('php/videoload.php', 'action=getTags&movieid=' + loadedvideoid, function (data) {
 | 
			
		||||
            for (const tag in data.tags) {
 | 
			
		||||
                $(".videoleftbanner").append(`<div>${tag}</div>`);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            console.log(data);
 | 
			
		||||
        }, "json");
 | 
			
		||||
 | 
			
		||||
        $("#likebtn").click(function () {
 | 
			
		||||
            console.log("likebtn clicked");
 | 
			
		||||
            $.post('php/videoload.php', 'action=addLike&movieid=' + loadedvideoid, function (data) {
 | 
			
		||||
                console.log(data);
 | 
			
		||||
            }, "json");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        $("#tagbutton").click(function () {
 | 
			
		||||
            console.log("tagbrn clicked");
 | 
			
		||||
            Swal.mixin({
 | 
			
		||||
                input: 'text',
 | 
			
		||||
                confirmButtonText: 'Next →',
 | 
			
		||||
                showCancelButton: true,
 | 
			
		||||
                progressSteps: ['1', '2', '3']
 | 
			
		||||
            }).queue([
 | 
			
		||||
                {
 | 
			
		||||
                    title: 'Question 1',
 | 
			
		||||
                    text: 'Chaining swal2 modals is easy'
 | 
			
		||||
                },
 | 
			
		||||
                'Question 2',
 | 
			
		||||
                'Question 3'
 | 
			
		||||
            ]).then((result) => {
 | 
			
		||||
                if (result.value) {
 | 
			
		||||
                    const answers = JSON.stringify(result.value)
 | 
			
		||||
                    Swal.fire({
 | 
			
		||||
                        title: 'All done!',
 | 
			
		||||
                        html: `
 | 
			
		||||
        Your answers:
 | 
			
		||||
        <pre><code>${answers}</code></pre>
 | 
			
		||||
      `,
 | 
			
		||||
                        confirmButtonText: 'Lovely!'
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        $(".videopagewrapper").show();
 | 
			
		||||
        $(".previewcontainer").hide();
 | 
			
		||||
    }, "json");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14053
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										14053
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										37
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "untitled",
 | 
			
		||||
  "version": "0.1.0",
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@testing-library/jest-dom": "^4.2.4",
 | 
			
		||||
    "@testing-library/react": "^9.5.0",
 | 
			
		||||
    "@testing-library/user-event": "^7.2.1",
 | 
			
		||||
    "bootstrap": "^4.5.0",
 | 
			
		||||
    "react": "^16.13.1",
 | 
			
		||||
    "react-dom": "^16.13.1",
 | 
			
		||||
    "react-scripts": "3.4.1",
 | 
			
		||||
    "plyr-react": "2.2.0"
 | 
			
		||||
  },
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "start": "react-scripts start",
 | 
			
		||||
    "build": "react-scripts build",
 | 
			
		||||
    "test": "react-scripts test",
 | 
			
		||||
    "eject": "react-scripts eject"
 | 
			
		||||
  },
 | 
			
		||||
  "proxy": "http://127.0.0.1:4000",
 | 
			
		||||
  "eslintConfig": {
 | 
			
		||||
    "extends": "react-app"
 | 
			
		||||
  },
 | 
			
		||||
  "browserslist": {
 | 
			
		||||
    "production": [
 | 
			
		||||
      ">0.2%",
 | 
			
		||||
      "not dead",
 | 
			
		||||
      "not op_mini all"
 | 
			
		||||
    ],
 | 
			
		||||
    "development": [
 | 
			
		||||
      "last 1 chrome version",
 | 
			
		||||
      "last 1 firefox version",
 | 
			
		||||
      "last 1 safari version"
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								public/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 3.1 KiB  | 
							
								
								
									
										43
									
								
								public/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								public/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="utf-8" />
 | 
			
		||||
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1" />
 | 
			
		||||
    <meta name="theme-color" content="#000000" />
 | 
			
		||||
    <meta
 | 
			
		||||
      name="description"
 | 
			
		||||
      content="Web site created using create-react-app"
 | 
			
		||||
    />
 | 
			
		||||
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
 | 
			
		||||
    <!--
 | 
			
		||||
      manifest.json provides metadata used when your web app is installed on a
 | 
			
		||||
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
 | 
			
		||||
    -->
 | 
			
		||||
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
 | 
			
		||||
    <!--
 | 
			
		||||
      Notice the use of %PUBLIC_URL% in the tags above.
 | 
			
		||||
      It will be replaced with the URL of the `public` folder during the build.
 | 
			
		||||
      Only files inside the `public` folder can be referenced from the HTML.
 | 
			
		||||
 | 
			
		||||
      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
 | 
			
		||||
      work correctly both with client-side routing and a non-root public URL.
 | 
			
		||||
      Learn how to configure a non-root public URL by running `npm run build`.
 | 
			
		||||
    -->
 | 
			
		||||
    <title>React App</title>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    <noscript>You need to enable JavaScript to run this app.</noscript>
 | 
			
		||||
    <div id="root"></div>
 | 
			
		||||
    <!--
 | 
			
		||||
      This HTML file is a template.
 | 
			
		||||
      If you open it directly in the browser, you will see an empty page.
 | 
			
		||||
 | 
			
		||||
      You can add webfonts, meta tags, or analytics to this file.
 | 
			
		||||
      The build step will place the bundled scripts into the <body> tag.
 | 
			
		||||
 | 
			
		||||
      To begin the development, run `npm start` or `yarn start`.
 | 
			
		||||
      To create a production bundle, use `npm run build` or `yarn build`.
 | 
			
		||||
    -->
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								public/logo192.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/logo192.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 5.2 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/logo512.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/logo512.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 9.4 KiB  | 
							
								
								
									
										25
									
								
								public/manifest.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								public/manifest.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
{
 | 
			
		||||
  "short_name": "React App",
 | 
			
		||||
  "name": "Create React App Sample",
 | 
			
		||||
  "icons": [
 | 
			
		||||
    {
 | 
			
		||||
      "src": "favicon.ico",
 | 
			
		||||
      "sizes": "64x64 32x32 24x24 16x16",
 | 
			
		||||
      "type": "image/x-icon"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "src": "logo192.png",
 | 
			
		||||
      "type": "image/png",
 | 
			
		||||
      "sizes": "192x192"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "src": "logo512.png",
 | 
			
		||||
      "type": "image/png",
 | 
			
		||||
      "sizes": "512x512"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "start_url": ".",
 | 
			
		||||
  "display": "standalone",
 | 
			
		||||
  "theme_color": "#000000",
 | 
			
		||||
  "background_color": "#ffffff"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								public/robots.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								public/robots.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
# https://www.robotstxt.org/robotstxt.html
 | 
			
		||||
User-agent: *
 | 
			
		||||
Disallow:
 | 
			
		||||
							
								
								
									
										85
									
								
								random.html
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								random.html
									
									
									
									
									
								
							@@ -1,85 +0,0 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en" dir="ltr">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="utf-8">
 | 
			
		||||
    <title>hub</title>
 | 
			
		||||
    <link rel="stylesheet" href="css/plyr.css"/>
 | 
			
		||||
    <link rel="stylesheet" href="css/video.css">
 | 
			
		||||
    <link rel="stylesheet" href="css/random.css">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <!-- Latest compiled and minified CSS -->
 | 
			
		||||
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
 | 
			
		||||
 | 
			
		||||
    <!-- jQuery library -->
 | 
			
		||||
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
 | 
			
		||||
 | 
			
		||||
    <!-- Popper JS -->
 | 
			
		||||
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
 | 
			
		||||
 | 
			
		||||
    <!-- Latest compiled JavaScript -->
 | 
			
		||||
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
 | 
			
		||||
 | 
			
		||||
    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@9"></script>
 | 
			
		||||
 | 
			
		||||
    <script src="js/plyr.js"></script>
 | 
			
		||||
    <script src="js/random.js"></script>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
<!-- Grey with black text -->
 | 
			
		||||
<nav class="navbar navbar-expand-sm bg-primary navbar-dark">
 | 
			
		||||
    <!-- Brand -->
 | 
			
		||||
    <a class="navbar-brand" href="#">Lukis Tube</a>
 | 
			
		||||
 | 
			
		||||
    <ul class="navbar-nav">
 | 
			
		||||
        <li class="nav-item">
 | 
			
		||||
            <a class="nav-link" href="index.html">Home</a>
 | 
			
		||||
        </li>
 | 
			
		||||
        <li class="nav-item active">
 | 
			
		||||
            <a class="nav-link" href="random.html">Random Video</a>
 | 
			
		||||
        </li>
 | 
			
		||||
        <li class="nav-item">
 | 
			
		||||
            <a class="nav-link" href="category.html">Categories</a>
 | 
			
		||||
        </li>
 | 
			
		||||
    </ul>
 | 
			
		||||
</nav>
 | 
			
		||||
 | 
			
		||||
<div class="videopagewrapper hideit">
 | 
			
		||||
    <div class="row">
 | 
			
		||||
        <div class="col-sm-2">
 | 
			
		||||
            <div class="videoleftbanner">
 | 
			
		||||
                <div class="likefield">Likes: 10</div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-sm-8">
 | 
			
		||||
            <div class="videowrapper"></div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-sm-2">
 | 
			
		||||
            <div class="closebutton">Close</div>
 | 
			
		||||
            <div class="videorightbanner"></div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="row">
 | 
			
		||||
        <div class="col-sm-5">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-sm-2">
 | 
			
		||||
            <button id="likebtn">Like it!</button>
 | 
			
		||||
            <button id="tagbutton">Tag it!</button>
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-sm-5">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<div class="previewcontainer">
 | 
			
		||||
</div>
 | 
			
		||||
<div style="width: 100%"><button type="button" id="shufflebtn" class="btn btn-success">Shuffle</button></div>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										71
									
								
								src/App.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/App.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import MainBody from "./MainBody";
 | 
			
		||||
 | 
			
		||||
import 'bootstrap/dist/css/bootstrap.min.css';
 | 
			
		||||
 | 
			
		||||
class App extends React.Component {
 | 
			
		||||
    constructor(props, context) {
 | 
			
		||||
        super(props, context);
 | 
			
		||||
        this.state = {page: "default"};
 | 
			
		||||
 | 
			
		||||
        // bind this to the method for being able to call methods such as this.setstate
 | 
			
		||||
        this.showVideo = this.showVideo.bind(this);
 | 
			
		||||
        this.hideVideo = this.hideVideo.bind(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render() {
 | 
			
		||||
        return (
 | 
			
		||||
            <div className="App">
 | 
			
		||||
                <nav className="navbar navbar-expand-sm bg-primary navbar-dark">
 | 
			
		||||
                    <a className="navbar-brand" href="!#">Lukis Tube</a>
 | 
			
		||||
 | 
			
		||||
                    <ul className="navbar-nav">
 | 
			
		||||
                        <li className="nav-item">
 | 
			
		||||
                            <a className="nav-link" onClick={() => this.loadHomePage()} href='# '>Home</a>
 | 
			
		||||
                        </li>
 | 
			
		||||
                        <li className="nav-item">
 | 
			
		||||
                            <a className="nav-link" onClick={() => this.loadRandomPage()} href="# ">Random Video</a>
 | 
			
		||||
                        </li>
 | 
			
		||||
                        <li className="nav-item">
 | 
			
		||||
                            <a className="nav-link" onClick={() => this.loadCategoriesPage()} href="# ">Categories</a>
 | 
			
		||||
                        </li>
 | 
			
		||||
                    </ul>
 | 
			
		||||
                </nav>
 | 
			
		||||
                <MainBody viewbinding={{showVideo: this.showVideo, hideVideo: this.hideVideo}} page={this.state.page}
 | 
			
		||||
                          videoelement={this.element}/>
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    loadCategoriesPage() {
 | 
			
		||||
        console.log("click categories");
 | 
			
		||||
        this.setState({page: "categories"});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    loadRandomPage() {
 | 
			
		||||
        console.log("click random");
 | 
			
		||||
        this.setState({page: "random"});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    loadHomePage() {
 | 
			
		||||
        console.log("click default");
 | 
			
		||||
        this.setState({page: "default"});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    showVideo(element) {
 | 
			
		||||
        this.setState({
 | 
			
		||||
            page: "video"
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.element = element;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hideVideo() {
 | 
			
		||||
        this.setState({
 | 
			
		||||
            page: "default"
 | 
			
		||||
        });
 | 
			
		||||
        this.element = null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default App;
 | 
			
		||||
							
								
								
									
										91
									
								
								src/HomePage.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/HomePage.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
import Preview from "./Preview";
 | 
			
		||||
import "./css/HomePage.css"
 | 
			
		||||
 | 
			
		||||
class HomePage extends React.Component {
 | 
			
		||||
    // stores all available movies
 | 
			
		||||
    data = null;
 | 
			
		||||
    // stores current index of loaded elements
 | 
			
		||||
    loadindex = 0;
 | 
			
		||||
 | 
			
		||||
    constructor(props, context) {
 | 
			
		||||
        super(props, context);
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            loadeditems: []
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidMount() {
 | 
			
		||||
        document.addEventListener('scroll', this.trackScrolling);
 | 
			
		||||
 | 
			
		||||
        const updateRequest = new FormData();
 | 
			
		||||
        updateRequest.append('action', 'getMovies');
 | 
			
		||||
 | 
			
		||||
        // fetch all videos available
 | 
			
		||||
        fetch('/php/videoload.php', {method: 'POST', body: updateRequest})
 | 
			
		||||
            .then((response) => response.json())
 | 
			
		||||
            .then((result) => {
 | 
			
		||||
                this.data = result;
 | 
			
		||||
                this.loadPreviewBlock(12);
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentWillUnmount() {
 | 
			
		||||
        this.setState({});
 | 
			
		||||
        document.removeEventListener('scroll', this.trackScrolling);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render() {
 | 
			
		||||
        return (
 | 
			
		||||
            <div>
 | 
			
		||||
                <div><h1>Home page</h1></div>
 | 
			
		||||
                <div className='sideinfo'>
 | 
			
		||||
                    beep beep
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className='maincontent'>
 | 
			
		||||
                    {this.state.loadeditems.map(elem => (
 | 
			
		||||
                        <Preview
 | 
			
		||||
                            key={elem.movie_id}
 | 
			
		||||
                            name={elem.movie_name}
 | 
			
		||||
                            movie_id={elem.movie_id}
 | 
			
		||||
                            viewbinding={this.props.viewbinding}/>
 | 
			
		||||
                    ))}
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className='rightinfo'>
 | 
			
		||||
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    loadPreviewBlock(nr) {
 | 
			
		||||
        console.log("loadpreviewblock called ...")
 | 
			
		||||
        let ret = [];
 | 
			
		||||
        for (let i = 0; i < nr; i++) {
 | 
			
		||||
            // only add if not end
 | 
			
		||||
            if (this.data.length > this.loadindex + i) {
 | 
			
		||||
                ret.push(this.data[this.loadindex + i]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.setState({
 | 
			
		||||
            loadeditems: [
 | 
			
		||||
                ...this.state.loadeditems,
 | 
			
		||||
                ...ret
 | 
			
		||||
            ]
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        this.loadindex += nr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    trackScrolling = (e) => {
 | 
			
		||||
        if (window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight) {
 | 
			
		||||
            this.loadPreviewBlock(6);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default HomePage;
 | 
			
		||||
							
								
								
									
										24
									
								
								src/MainBody.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/MainBody.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
import HomePage from "./HomePage";
 | 
			
		||||
 | 
			
		||||
class MainBody extends React.Component {
 | 
			
		||||
    constructor(props) {
 | 
			
		||||
        super(props);
 | 
			
		||||
        this.props = props;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render() {
 | 
			
		||||
        let page;
 | 
			
		||||
        if (this.props.page === "default") {
 | 
			
		||||
            page = <HomePage viewbinding={this.props.viewbinding}/>;
 | 
			
		||||
        } else if (this.props.page === "video") {
 | 
			
		||||
            // show videoelement if neccessary
 | 
			
		||||
            page = this.props.videoelement;
 | 
			
		||||
        } else {
 | 
			
		||||
            page = <div>unimplemented yet!</div>;
 | 
			
		||||
        }
 | 
			
		||||
        return (page);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default MainBody;
 | 
			
		||||
							
								
								
									
										128
									
								
								src/Player.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/Player.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
import "./css/Player.css"
 | 
			
		||||
import {PlyrComponent} from 'plyr-react';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Player extends React.Component {
 | 
			
		||||
    constructor(props, context) {
 | 
			
		||||
        super(props, context);
 | 
			
		||||
 | 
			
		||||
        this.state = {};
 | 
			
		||||
 | 
			
		||||
        this.props = props;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
        ]
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    componentDidMount() {
 | 
			
		||||
        this.fetchMovieData();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render() {
 | 
			
		||||
        return (
 | 
			
		||||
            <div>
 | 
			
		||||
                <div className="row">
 | 
			
		||||
                    <div className="col-sm-2">
 | 
			
		||||
                        <div className="videoleftbanner">
 | 
			
		||||
                            <div className="likefield">Likes: {this.state.likes}</div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className="col-sm-8">
 | 
			
		||||
                        <div className="videowrapper">
 | 
			
		||||
                            <div className='myvideo'>
 | 
			
		||||
                                {this.state.sources ? <PlyrComponent
 | 
			
		||||
                                        sources={this.state.sources}
 | 
			
		||||
                                        options={this.options}/> :
 | 
			
		||||
                                    <div>not loaded yet</div>}
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className="col-sm-2">
 | 
			
		||||
                        <div className="closebutton" onClick={() => {this.closebtn()}}>Close</div>
 | 
			
		||||
                        <div className="videorightbanner"></div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className="row">
 | 
			
		||||
                    <div className="col-sm-5">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className="col-sm-2">
 | 
			
		||||
                        <button className='btn btn-primary' onClick={() => {this.likebtn()}}>Like it!</button>
 | 
			
		||||
                        <button className='btn btn-info' id="tagbutton">Tag it!</button>
 | 
			
		||||
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className="col-sm-5">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fetchMovieData(){
 | 
			
		||||
        const updateRequest = new FormData();
 | 
			
		||||
        updateRequest.append('action', 'loadVideo');
 | 
			
		||||
        updateRequest.append('movieid', this.props.movie_id);
 | 
			
		||||
 | 
			
		||||
        fetch('/php/videoload.php', {method: 'POST', body: updateRequest})
 | 
			
		||||
            .then((response) => response.json())
 | 
			
		||||
            .then((result) => {
 | 
			
		||||
                this.setState({
 | 
			
		||||
                    sources: {
 | 
			
		||||
                        type: 'video',
 | 
			
		||||
                        sources: [
 | 
			
		||||
                            {
 | 
			
		||||
                                src: result.movie_url,
 | 
			
		||||
                                type: 'video/mp4',
 | 
			
		||||
                                size: 1080,
 | 
			
		||||
                            }
 | 
			
		||||
                        ],
 | 
			
		||||
                        poster: result.thumbnail
 | 
			
		||||
                    },
 | 
			
		||||
                    likes: result.likes
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /* Click Listener */
 | 
			
		||||
    likebtn() {
 | 
			
		||||
        const updateRequest = new FormData();
 | 
			
		||||
        updateRequest.append('action', 'addLike');
 | 
			
		||||
        updateRequest.append('movieid', this.props.movie_id);
 | 
			
		||||
 | 
			
		||||
        fetch('/php/videoload.php', {method: 'POST', body: updateRequest})
 | 
			
		||||
            .then((response) => response.json())
 | 
			
		||||
            .then((result) => {
 | 
			
		||||
                if(result.result === "success"){
 | 
			
		||||
                    this.fetchMovieData();
 | 
			
		||||
                }else{
 | 
			
		||||
                    console.log("an error occured while liking");
 | 
			
		||||
                    console.log(result);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    closebtn() {
 | 
			
		||||
        this.props.viewbinding.hideVideo();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default Player;
 | 
			
		||||
							
								
								
									
										59
									
								
								src/Preview.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/Preview.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
import "./css/Preview.css"
 | 
			
		||||
import Player from "./Player";
 | 
			
		||||
 | 
			
		||||
class Preview extends React.Component {
 | 
			
		||||
    constructor(props, context) {
 | 
			
		||||
        super(props, context);
 | 
			
		||||
        this.props = props;
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            previewpicture: null,
 | 
			
		||||
            name: null
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentWillUnmount() {
 | 
			
		||||
        this.setState({});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidMount() {
 | 
			
		||||
        this.setState({
 | 
			
		||||
            previewpicture: null,
 | 
			
		||||
            name: this.props.name
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        const updateRequest = new FormData();
 | 
			
		||||
        updateRequest.append('action', 'readThumbnail');
 | 
			
		||||
        updateRequest.append('movieid', this.props.movie_id);
 | 
			
		||||
 | 
			
		||||
        fetch('/php/videoload.php', {method: 'POST', body: updateRequest})
 | 
			
		||||
            .then((response) => response.text())
 | 
			
		||||
            .then((result) => {
 | 
			
		||||
                this.setState(prevState => ({
 | 
			
		||||
                    ...prevState.previewpicture, previewpicture: result
 | 
			
		||||
                }));
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render() {
 | 
			
		||||
        return (
 | 
			
		||||
            <div className='videopreview' onClick={() => this.itemClick()}>
 | 
			
		||||
                <div className='previewtitle'>{this.state.name}</div>
 | 
			
		||||
                <div className='previewpic'>
 | 
			
		||||
                    <img className='previewimage'
 | 
			
		||||
                         src={this.state.previewpicture}
 | 
			
		||||
                         alt='no thumbnail found'/>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    itemClick() {
 | 
			
		||||
        console.log("item clicked!" + this.state.name);
 | 
			
		||||
 | 
			
		||||
        this.props.viewbinding.showVideo(<Player viewbinding={this.props.viewbinding} movie_id={this.props.movie_id}/>);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default Preview;
 | 
			
		||||
							
								
								
									
										14
									
								
								src/css/HomePage.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/css/HomePage.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
.sideinfo{
 | 
			
		||||
    width: 20%;
 | 
			
		||||
    float: left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.maincontent{
 | 
			
		||||
    float: left;
 | 
			
		||||
    width: 70%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.rightinfo{
 | 
			
		||||
    float: left;
 | 
			
		||||
    width: 10%;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,3 @@
 | 
			
		||||
.hideit {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.closebutton {
 | 
			
		||||
    color: white;
 | 
			
		||||
    height: 35px;
 | 
			
		||||
@@ -35,36 +31,3 @@
 | 
			
		||||
    color: white;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.previewcontainer {
 | 
			
		||||
    margin-left: 10%;
 | 
			
		||||
    width: 80%;
 | 
			
		||||
    margin-right: 10%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.videopreview {
 | 
			
		||||
    height: 300px;
 | 
			
		||||
    width: 30%;
 | 
			
		||||
    float: left;
 | 
			
		||||
    margin: 1%;
 | 
			
		||||
    background-color: #7F7F7F;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    opacity: 0.9;
 | 
			
		||||
    border: 10px;
 | 
			
		||||
    border-radius: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.videopreview:hover {
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
    transition: opacity 0.5s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.previewtitle {
 | 
			
		||||
    height: 10%;
 | 
			
		||||
    color: white;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.previewpic {
 | 
			
		||||
    height: 80%;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								src/css/Preview.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/css/Preview.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
.previewtitle {
 | 
			
		||||
    height: 10%;
 | 
			
		||||
    color: white;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.previewpic {
 | 
			
		||||
    height: 80%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.previewimage{
 | 
			
		||||
    width:100%;
 | 
			
		||||
    height:100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.videopreview {
 | 
			
		||||
    height: 300px;
 | 
			
		||||
    width: 30%;
 | 
			
		||||
    float: left;
 | 
			
		||||
    margin: 1%;
 | 
			
		||||
    background-color: #7F7F7F;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    opacity: 0.9;
 | 
			
		||||
    border: 10px;
 | 
			
		||||
    border-radius: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.videopreview:hover {
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
    transition: opacity 0.5s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* todo check if neccessary*/
 | 
			
		||||
.previewcontainer {
 | 
			
		||||
    margin-left: 10%;
 | 
			
		||||
    width: 80%;
 | 
			
		||||
    margin-right: 10%;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/css/index.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/css/index.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
body {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
 | 
			
		||||
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
 | 
			
		||||
    sans-serif;
 | 
			
		||||
    -webkit-font-smoothing: antialiased;
 | 
			
		||||
    -moz-osx-font-smoothing: grayscale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
code {
 | 
			
		||||
    font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
 | 
			
		||||
    monospace;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								src/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import ReactDOM from 'react-dom';
 | 
			
		||||
import './css/index.css';
 | 
			
		||||
import App from './App';
 | 
			
		||||
import * as serviceWorker from './serviceWorker';
 | 
			
		||||
 | 
			
		||||
ReactDOM.render(
 | 
			
		||||
  <React.StrictMode>
 | 
			
		||||
    <App />
 | 
			
		||||
  </React.StrictMode>,
 | 
			
		||||
  document.getElementById('root')
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
// If you want your app to work offline and load faster, you can change
 | 
			
		||||
// unregister() to register() below. Note this comes with some pitfalls.
 | 
			
		||||
// Learn more about service workers: https://bit.ly/CRA-PWA
 | 
			
		||||
serviceWorker.register();
 | 
			
		||||
							
								
								
									
										141
									
								
								src/serviceWorker.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								src/serviceWorker.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,141 @@
 | 
			
		||||
// This optional code is used to register a service worker.
 | 
			
		||||
// register() is not called by default.
 | 
			
		||||
 | 
			
		||||
// This lets the app load faster on subsequent visits in production, and gives
 | 
			
		||||
// it offline capabilities. However, it also means that developers (and users)
 | 
			
		||||
// will only see deployed updates on subsequent visits to a page, after all the
 | 
			
		||||
// existing tabs open on the page have been closed, since previously cached
 | 
			
		||||
// resources are updated in the background.
 | 
			
		||||
 | 
			
		||||
// To learn more about the benefits of this model and instructions on how to
 | 
			
		||||
// opt-in, read https://bit.ly/CRA-PWA
 | 
			
		||||
 | 
			
		||||
const isLocalhost = Boolean(
 | 
			
		||||
  window.location.hostname === 'localhost' ||
 | 
			
		||||
    // [::1] is the IPv6 localhost address.
 | 
			
		||||
    window.location.hostname === '[::1]' ||
 | 
			
		||||
    // 127.0.0.0/8 are considered localhost for IPv4.
 | 
			
		||||
    window.location.hostname.match(
 | 
			
		||||
      /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
 | 
			
		||||
    )
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export function register(config) {
 | 
			
		||||
  if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
 | 
			
		||||
    // The URL constructor is available in all browsers that support SW.
 | 
			
		||||
    const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
 | 
			
		||||
    if (publicUrl.origin !== window.location.origin) {
 | 
			
		||||
      // Our service worker won't work if PUBLIC_URL is on a different origin
 | 
			
		||||
      // from what our page is served on. This might happen if a CDN is used to
 | 
			
		||||
      // serve assets; see https://github.com/facebook/create-react-app/issues/2374
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    window.addEventListener('load', () => {
 | 
			
		||||
      const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
 | 
			
		||||
 | 
			
		||||
      if (isLocalhost) {
 | 
			
		||||
        // This is running on localhost. Let's check if a service worker still exists or not.
 | 
			
		||||
        checkValidServiceWorker(swUrl, config);
 | 
			
		||||
 | 
			
		||||
        // Add some additional logging to localhost, pointing developers to the
 | 
			
		||||
        // service worker/PWA documentation.
 | 
			
		||||
        navigator.serviceWorker.ready.then(() => {
 | 
			
		||||
          console.log(
 | 
			
		||||
            'This web app is being served cache-first by a service ' +
 | 
			
		||||
              'worker. To learn more, visit https://bit.ly/CRA-PWA'
 | 
			
		||||
          );
 | 
			
		||||
        });
 | 
			
		||||
      } else {
 | 
			
		||||
        // Is not localhost. Just register service worker
 | 
			
		||||
        registerValidSW(swUrl, config);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function registerValidSW(swUrl, config) {
 | 
			
		||||
  navigator.serviceWorker
 | 
			
		||||
    .register(swUrl)
 | 
			
		||||
    .then(registration => {
 | 
			
		||||
      registration.onupdatefound = () => {
 | 
			
		||||
        const installingWorker = registration.installing;
 | 
			
		||||
        if (installingWorker == null) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        installingWorker.onstatechange = () => {
 | 
			
		||||
          if (installingWorker.state === 'installed') {
 | 
			
		||||
            if (navigator.serviceWorker.controller) {
 | 
			
		||||
              // At this point, the updated precached content has been fetched,
 | 
			
		||||
              // but the previous service worker will still serve the older
 | 
			
		||||
              // content until all client tabs are closed.
 | 
			
		||||
              console.log(
 | 
			
		||||
                'New content is available and will be used when all ' +
 | 
			
		||||
                  'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
 | 
			
		||||
              );
 | 
			
		||||
 | 
			
		||||
              // Execute callback
 | 
			
		||||
              if (config && config.onUpdate) {
 | 
			
		||||
                config.onUpdate(registration);
 | 
			
		||||
              }
 | 
			
		||||
            } else {
 | 
			
		||||
              // At this point, everything has been precached.
 | 
			
		||||
              // It's the perfect time to display a
 | 
			
		||||
              // "Content is cached for offline use." message.
 | 
			
		||||
              console.log('Content is cached for offline use.');
 | 
			
		||||
 | 
			
		||||
              // Execute callback
 | 
			
		||||
              if (config && config.onSuccess) {
 | 
			
		||||
                config.onSuccess(registration);
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
    })
 | 
			
		||||
    .catch(error => {
 | 
			
		||||
      console.error('Error during service worker registration:', error);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function checkValidServiceWorker(swUrl, config) {
 | 
			
		||||
  // Check if the service worker can be found. If it can't reload the page.
 | 
			
		||||
  fetch(swUrl, {
 | 
			
		||||
    headers: { 'Service-Worker': 'script' },
 | 
			
		||||
  })
 | 
			
		||||
    .then(response => {
 | 
			
		||||
      // Ensure service worker exists, and that we really are getting a JS file.
 | 
			
		||||
      const contentType = response.headers.get('content-type');
 | 
			
		||||
      if (
 | 
			
		||||
        response.status === 404 ||
 | 
			
		||||
        (contentType != null && contentType.indexOf('javascript') === -1)
 | 
			
		||||
      ) {
 | 
			
		||||
        // No service worker found. Probably a different app. Reload the page.
 | 
			
		||||
        navigator.serviceWorker.ready.then(registration => {
 | 
			
		||||
          registration.unregister().then(() => {
 | 
			
		||||
            window.location.reload();
 | 
			
		||||
          });
 | 
			
		||||
        });
 | 
			
		||||
      } else {
 | 
			
		||||
        // Service worker found. Proceed as normal.
 | 
			
		||||
        registerValidSW(swUrl, config);
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    .catch(() => {
 | 
			
		||||
      console.log(
 | 
			
		||||
        'No internet connection found. App is running in offline mode.'
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function unregister() {
 | 
			
		||||
  if ('serviceWorker' in navigator) {
 | 
			
		||||
    navigator.serviceWorker.ready
 | 
			
		||||
      .then(registration => {
 | 
			
		||||
        registration.unregister();
 | 
			
		||||
      })
 | 
			
		||||
      .catch(error => {
 | 
			
		||||
        console.error(error.message);
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								src/setupTests.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/setupTests.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
 | 
			
		||||
// allows you to do things like:
 | 
			
		||||
// expect(element).toHaveTextContent(/react/i)
 | 
			
		||||
// learn more: https://github.com/testing-library/jest-dom
 | 
			
		||||
import '@testing-library/jest-dom/extend-expect';
 | 
			
		||||
		Reference in New Issue
	
	Block a user