diff --git a/api/videoload.php b/api/videoload.php index 282aff0..fced3d9 100755 --- a/api/videoload.php +++ b/api/videoload.php @@ -11,7 +11,7 @@ if (isset($_POST['action'])) { $query = "SELECT movie_id,movie_name FROM videos ORDER BY likes DESC, create_date ASC, movie_name ASC"; if (isset($_POST['tag'])) { $tag = $_POST['tag']; - if($_POST['tag'] != "all"){ + if ($_POST['tag'] != "all") { $query = "SELECT movie_id,movie_name FROM videos INNER JOIN video_tags vt on videos.movie_id = vt.video_id INNER JOIN tags t on vt.tag_id = t.tag_id @@ -28,7 +28,7 @@ if (isset($_POST['action'])) { echo(json_encode($rows)); break; case "getRandomMovies": - $query = "SELECT movie_id,movie_name FROM videos ORDER BY RAND() LIMIT ".$_POST['number']; + $query = "SELECT movie_id,movie_name FROM videos ORDER BY RAND() LIMIT " . $_POST['number']; $result = $conn->query($query); $rows = array(); while ($r = mysqli_fetch_assoc($result)) { @@ -38,13 +38,14 @@ if (isset($_POST['action'])) { echo(json_encode($rows)); break; case "loadVideo": - $query = "SELECT movie_url,thumbnail,likes,quality,length FROM videos WHERE movie_id='" . $_POST['movieid'] . "'"; + $query = "SELECT movie_name,movie_url,thumbnail,likes,quality,length FROM videos WHERE movie_id='" . $_POST['movieid'] . "'"; $result = $conn->query($query); $row = $result->fetch_assoc(); $arr = array(); $arr["thumbnail"] = $row["thumbnail"]; + $arr["movie_name"] = $row["movie_name"]; $arr["movie_url"] = $row["movie_url"]; $arr["likes"] = $row["likes"]; $arr["quality"] = $row["quality"]; @@ -75,7 +76,6 @@ if (isset($_POST['action'])) { echo($row["thumbnail"]); break; - case "getTags": $movieid = $_POST['movieid']; @@ -104,6 +104,52 @@ if (isset($_POST['action'])) { echo('{"result":"' . $conn->error . '"}'); } break; + case "getStartData": + $query = "SELECT COUNT(*) as nr FROM videos"; + $result = $conn->query($query); + $r = mysqli_fetch_assoc($result); + + $arr = array(); + $arr['total'] = $r['nr']; + + $query = "SELECT COUNT(*) as nr FROM videos + INNER JOIN video_tags vt on videos.movie_id = vt.video_id + INNER JOIN tags t on vt.tag_id = t.tag_id"; + $result = $conn->query($query); + $r = mysqli_fetch_assoc($result); + $arr['tagged'] = $r['nr']; + + $query = "SELECT COUNT(*) as nr FROM videos + INNER JOIN video_tags vt on videos.movie_id = vt.video_id + INNER JOIN tags t on vt.tag_id = t.tag_id + WHERE t.tag_name='hd'"; + $result = $conn->query($query); + $r = mysqli_fetch_assoc($result); + $arr['hd'] = $r['nr']; + + $query = "SELECT COUNT(*) as nr FROM videos + INNER JOIN video_tags vt on videos.movie_id = vt.video_id + INNER JOIN tags t on vt.tag_id = t.tag_id + WHERE t.tag_name='fullhd'"; + $result = $conn->query($query); + $r = mysqli_fetch_assoc($result); + $arr['fullhd'] = $r['nr']; + + $query = "SELECT COUNT(*) as nr FROM videos + INNER JOIN video_tags vt on videos.movie_id = vt.video_id + INNER JOIN tags t on vt.tag_id = t.tag_id + WHERE t.tag_name='lowquality'"; + $result = $conn->query($query); + $r = mysqli_fetch_assoc($result); + $arr['sd'] = $r['nr']; + + $query = "SELECT COUNT(*) as nr FROM tags"; + $result = $conn->query($query); + $r = mysqli_fetch_assoc($result); + $arr['tags'] = $r['nr']; + + echo(json_encode($arr)); + break; } } else { echo('{"data":"error"}'); diff --git a/src/App.js b/src/App.js index d52be75..ec1eb14 100644 --- a/src/App.js +++ b/src/App.js @@ -1,6 +1,7 @@ import React from 'react'; -import MainBody from "./MainBody"; import "./css/App.css" +import HomePage from "./HomePage"; +import RandomPage from "./RandomPage"; // include bootstraps css import 'bootstrap/dist/css/bootstrap.min.css'; @@ -15,6 +16,28 @@ class App extends React.Component { this.hideVideo = this.hideVideo.bind(this); } + videoelement = null; + + MainBody() { + let page; + if (this.state.page === "default") { + page = ; + this.mypage = page; + } else if (this.state.page === "random") { + page = ; + this.mypage = page; + } else if (this.state.page === "video") { + // show videoelement if neccessary + page = this.videoelement; + } else if (this.state.page === "lastpage") { + // return back to last page + page = this.mypage; + } else { + page =
unimplemented yet!
; + } + return (page); + } + render() { return (
@@ -42,8 +65,7 @@ class App extends React.Component { - + {this.MainBody()}
); } @@ -68,7 +90,7 @@ class App extends React.Component { page: "video" }); - this.element = element; + this.videoelement = element; } hideVideo() { diff --git a/src/HomePage.js b/src/HomePage.js index 7b56431..56f222c 100644 --- a/src/HomePage.js +++ b/src/HomePage.js @@ -1,6 +1,9 @@ import React from "react"; import Preview from "./Preview"; +import SideBar from "./SideBar"; + import "./css/HomePage.css" +import "./css/DefaultPage.css" class HomePage extends React.Component { // stores all available movies @@ -15,9 +18,10 @@ class HomePage extends React.Component { loadeditems: [], sideinfo: { videonr: null, + fullhdvideonr: null, hdvideonr: null, sdvideonr: null, - categorynr: null + tagnr: null }, tag: "all" }; @@ -27,6 +31,7 @@ class HomePage extends React.Component { document.addEventListener('scroll', this.trackScrolling); // initial get of all videos this.fetchVideoData("all"); + this.fetchStartData(); } // this function clears all preview elements an reloads gravity with tag @@ -41,7 +46,7 @@ class HomePage extends React.Component { .then((result) => { this.data = result; this.setState({loadeditems: []}); - this.loadindex=0; + this.loadindex = 0; this.loadPreviewBlock(12); })) .catch(() => { @@ -49,6 +54,28 @@ class HomePage extends React.Component { }); } + fetchStartData() { + const updateRequest = new FormData(); + updateRequest.append('action', 'getStartData'); + + // fetch all videos available + fetch('/api/videoload.php', {method: 'POST', body: updateRequest}) + .then((response) => response.json() + .then((result) => { + this.setState({ + sideinfo: { + videonr: result['total'], + fullhdvideonr: result['fullhd'], + hdvideonr: result['hd'], + sdvideonr: result['sd'], + tagnr: result['tags'] + }}); + })) + .catch(() => { + console.log("no connection to backend"); + }); + } + componentWillUnmount() { this.setState({}); document.removeEventListener('scroll', this.trackScrolling); @@ -57,32 +84,26 @@ class HomePage extends React.Component { render() { return (
-

Home page

-
- Infos: -
Total Number of Videos: {this.state.sideinfo.videonr}
-
HD Videos: {this.state.sideinfo.hdvideonr}
-
SD Videos: {this.state.sideinfo.sdvideonr}
-
Total Number of Categories: {this.state.sideinfo.categorynr}
- -
default tags:
- - - - +
+ Home Page + All Videos - {this.state.sideinfo.videonr} +
+ +
Infos:
+
+
{this.state.sideinfo.videonr} Videos Total!
+
{this.state.sideinfo.fullhdvideonr} FULL-HD Videos!
+
{this.state.sideinfo.hdvideonr} HD Videos!
+
{this.state.sideinfo.sdvideonr} SD Videos!
+
{this.state.sideinfo.tagnr} different Tags!
+
+
Default Tags:
+ + + + +
{this.state.loadeditems.map(elem => ( { - if (window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight) { + // comparison if current scroll position is on bottom + // 200 stands for bottom offset to trigger load + if (window.innerHeight + document.documentElement.scrollTop + 200 >= document.documentElement.offsetHeight) { this.loadPreviewBlock(6); } } diff --git a/src/MainBody.js b/src/MainBody.js deleted file mode 100644 index 66019ff..0000000 --- a/src/MainBody.js +++ /dev/null @@ -1,32 +0,0 @@ -import React from "react"; -import HomePage from "./HomePage"; -import RandomPage from "./RandomPage"; - -class MainBody extends React.Component { - constructor(props) { - super(props); - this.props = props; - } - - render() { - let page; - if (this.props.page === "default") { - page = ; - this.mypage = page; - } else if (this.props.page === "random"){ - page = ; - this.mypage = page; - }else if (this.props.page === "video") { - // show videoelement if neccessary - page = this.props.videoelement; - }else if (this.props.page === "lastpage") { - // return back to last page - page = this.mypage; - } else { - page =
unimplemented yet!
; - } - return (page); - } -} - -export default MainBody; diff --git a/src/Player.js b/src/Player.js index 1145af3..20c61a0 100644 --- a/src/Player.js +++ b/src/Player.js @@ -1,6 +1,7 @@ import React from "react"; import "./css/Player.css" import {PlyrComponent} from 'plyr-react'; +import SideBar from "./SideBar"; class Player extends React.Component { @@ -36,50 +37,38 @@ class Player extends React.Component { render() { return (
-
-
-
-
Likes: {this.state.likes}
-
Quality: {this.state.quality}p
-
Length in Minutes: {this.state.length}
-
-
-
-
-
- {this.state.sources ? : -
not loaded yet
} -
-
-
-
-
{ - this.closebtn() - }}>Close -
-
-
-
-
-
- - -
-
- - - -
-
- - +
+ Watch + {this.state.movie_name} +
+
+ +
Infos:
+
+
{this.state.likes} Likes!
+
{this.state.quality}p Quality!
+
{this.state.length} Minutes of length!
+
+
Tags:
+ + + + +
+ +
+ {/* video component is added here */} + {this.state.sources ? : +
not loaded yet
} +
+ +
+
); } @@ -104,6 +93,7 @@ class Player extends React.Component { ], poster: result.thumbnail }, + movie_name: result.movie_name, likes: result.likes, quality: result.quality, length: result.length @@ -131,8 +121,6 @@ class Player extends React.Component { } closebtn() { - // todo go back to correct page here! - // have a catch to this.props.viewbinding.hideVideo(); } } diff --git a/src/RandomPage.js b/src/RandomPage.js index a574ee6..7412280 100644 --- a/src/RandomPage.js +++ b/src/RandomPage.js @@ -1,6 +1,7 @@ import React from "react"; import Preview from "./Preview"; import "./css/RandomPage.css" +import SideBar from "./SideBar"; class RandomPage extends React.Component { constructor(props, context) { @@ -16,31 +17,35 @@ class RandomPage extends React.Component { } render() { - return (
-

Random Videos

-
- todo here. -
-
- {this.state.videos.map(elem => ( - - ))} -
-
- right -
-
- -
+ return ( +
+
+ Random Videos + 6pc +
+
+ +
Visible Tags:
+ + + + +
-
); +
+ {this.state.videos.map(elem => ( + + ))} +
+ +
+
+
+ ); } shuffleclick() { diff --git a/src/SideBar.js b/src/SideBar.js new file mode 100644 index 0000000..5c06447 --- /dev/null +++ b/src/SideBar.js @@ -0,0 +1,12 @@ +import React from "react"; +import "./css/SideBar.css" + +class SideBar extends React.Component { + render() { + return (
+ {this.props.children} +
); + } +} + +export default SideBar; diff --git a/src/css/App.css b/src/css/App.css index c00403f..af62d60 100644 --- a/src/css/App.css +++ b/src/css/App.css @@ -1,11 +1,12 @@ -.nav-item{ +.nav-item { cursor: pointer; } -.nav-link{ - color: rgba(255,255,255,.5); + +.nav-link { + color: rgba(255, 255, 255, .5); font-weight: bold; } -.nav-link:hover{ - color: rgba(255,255,255,1); -} \ No newline at end of file +.nav-link:hover { + color: rgba(255, 255, 255, 1); +} diff --git a/src/css/DefaultPage.css b/src/css/DefaultPage.css new file mode 100644 index 0000000..5f6d3da --- /dev/null +++ b/src/css/DefaultPage.css @@ -0,0 +1,18 @@ +.pageheader { + margin-top: 20px; + margin-bottom: 20px; + padding-left: 22%; + padding-right: 12%; +} + +.pageheadertitle { + font-size: 40pt; + font-weight: bold; +} + +.pageheadersubtitle { + margin-left: 20px; + font-size: 23pt; + opacity: 0.6; +} + diff --git a/src/css/HomePage.css b/src/css/HomePage.css index bf3660e..af62c3d 100644 --- a/src/css/HomePage.css +++ b/src/css/HomePage.css @@ -1,14 +1,9 @@ -.sideinfo{ - width: 20%; - float: left; -} - -.maincontent{ +.maincontent { float: left; width: 70%; } -.rightinfo{ +.rightinfo { float: left; width: 10%; -} \ No newline at end of file +} diff --git a/src/css/Player.css b/src/css/Player.css index 0f5b83c..dbbb649 100644 --- a/src/css/Player.css +++ b/src/css/Player.css @@ -1,26 +1,14 @@ .closebutton { color: white; - height: 35px; - width: 90px; - margin-right: 80px; - float: right; + border: none; + border-radius: 10px; + padding: 5px 15px 5px 15px; background-color: #FF0000; - cursor: pointer; + margin-top: 25px; + margin-left: 25px; } -.myvideo { - width: 100%; - float: left; -} - -.videoleftbanner{ - float: left; - width: 100%; - height: 100%; - background-color: #e5e5ff; - border-radius: 40px; -} -.likefield{ +.likefield { margin-top: 15px; margin-left: 15px; margin-right: 15px; @@ -29,5 +17,16 @@ border-radius: 10px; text-align: center; color: white; - +} + +.videowrapper { + margin-left: 20px; + display: block; + float: left; + width: 60%; + margin-top: 25px; +} + +.videoactions{ + margin-top: 15px; } diff --git a/src/css/Preview.css b/src/css/Preview.css index 863f7c1..8b4ae62 100644 --- a/src/css/Preview.css +++ b/src/css/Preview.css @@ -1,7 +1,8 @@ .previewtitle { height: 10%; - color: white; + color: #3d3d3d; text-align: center; + font-weight: bold; } .previewpic { @@ -17,8 +18,10 @@ height: 300px; width: 30%; float: left; - margin: 1%; - background-color: #7F7F7F; + margin-left: 25px; + margin-top: 25px; + /*background-color: #7F7F7F;*/ + background-color: #a8c3ff; cursor: pointer; opacity: 0.9; border: 10px; @@ -29,10 +32,3 @@ opacity: 1; transition: opacity 0.5s; } - -/* todo check if neccessary*/ -.previewcontainer { - margin-left: 10%; - width: 80%; - margin-right: 10%; -} diff --git a/src/css/RandomPage.css b/src/css/RandomPage.css index d8a06ac..d6a2e15 100644 --- a/src/css/RandomPage.css +++ b/src/css/RandomPage.css @@ -1,4 +1,21 @@ -.Shufflebutton{ +.Shufflebutton { width: 100%; align-content: center; -} \ No newline at end of file +} + +.btnshuffle{ + background-color: #39a945; + + color: white; + margin-top: 20px; + margin-left: 45%; + border: none; + border-radius: 10px; + padding: 15px 25px 15px 25px; + font-weight: bold; + font-size: larger; +} + +.btnshuffle:focus{ + outline: none; +} diff --git a/src/css/SideBar.css b/src/css/SideBar.css new file mode 100644 index 0000000..3083984 --- /dev/null +++ b/src/css/SideBar.css @@ -0,0 +1,43 @@ +.sideinfo { + width: 20%; + float: left; + padding: 20px; + margin-top: 25px; + margin-left: 15px; + background-color: #b4c7fe; + border-radius: 20px; + border: 2px #3574fe solid; +} + +.tagbtn { + color: white; + margin: 10px; + background-color: #3574fe; + border: none; + border-radius: 10px; + padding: 5px 15px 5px 15px; + /*font-weight: bold;*/ + display: block; +} + +.tagbtn:focus { + background-color: #004eff; + outline: none; +} + +.tagbtn:hover { + background-color: #004eff; +} + +.sidebartitle { + font-weight: bold; + font-size: larger; +} + +.sidebarinfo { + margin-top: 5px; + background-color: #8ca3fc; + border-radius: 5px; + padding: 2px 10px 2px 15px; + width: 60%; +} diff --git a/src/index.js b/src/index.js index b2bd394..b8d3abb 100644 --- a/src/index.js +++ b/src/index.js @@ -5,10 +5,10 @@ import App from './App'; import * as serviceWorker from './serviceWorker'; ReactDOM.render( - - - , - document.getElementById('root') + + + , + document.getElementById('root') ); // If you want your app to work offline and load faster, you can change diff --git a/src/serviceWorker.js b/src/serviceWorker.js index b04b771..e583a40 100644 --- a/src/serviceWorker.js +++ b/src/serviceWorker.js @@ -11,131 +11,131 @@ // opt-in, read https://bit.ly/CRA-PWA const isLocalhost = Boolean( - window.location.hostname === 'localhost' || + 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}$/ + /^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; - } + 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`; + 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); + 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' - ); + // 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); + } }); - } 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.' - ); + 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.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); - }); + // 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); - } + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl, { + headers: {'Service-Worker': 'script'}, }) - .catch(() => { - console.log( - 'No internet connection found. App is running in offline mode.' - ); - }); + .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); - }); - } + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready + .then(registration => { + registration.unregister(); + }) + .catch(error => { + console.error(error.message); + }); + } }