mirror of
https://github.com/tubearchivist/tubearchivist-frontend.git
synced 2024-11-22 20:00:15 +00:00
Get Video Player Data Using New API (#151)
* Get video player data using new API * Spelling * Removed extra data from play button * Reworked createPlayer, switched functions to API * Add theme to scrollbar * Removed extra metadata from playlist page * Removed extra metadat from channel page * Reworked createPlayer, switched functions to API * Update style.css * Changed watched indicator to match createVideo() * Fixed createPlayer() watched button * Fix watched indicator duplication * Minor clean up * Removed player-wrapper background * Added video/channel info to generated player * Removed description due to textReveal() conflict * Mark video as played at 90% playback * Groundwork for saving video playback * Add half and empty stars to getStarRating() * Check videoProgress input. * Added last refresh and date published * Switched date in create functions to API * Fomatted dates to match the old format * Remove console log from formatDates() * Cleaned up error on video player close * Added check for ryd dislikes/rating * Refined ryd check * Simplified player * Added player stats css formatting * Formatting for playlist name/link * Add playlist title/link to player * Commented out no longer used code * Fix missing end `"` on video-player class * Additional playlist error checking * Change setting video progress to html method * center thumbs icon, add eye icon for watched * add playerStats builder example, change some spacing * Removed `-` before playlist, reordered cast button * Minor cleanup of unused code. * Corrected POST data formating * consolidate video api calls into one * remove redundant api calls for search result population * do some jshint * shorten unit and add K to formatNumbers Co-authored-by: simon <simobilleter@gmail.com>
This commit is contained in:
parent
8591c44ef2
commit
9079a2a78b
@ -106,7 +106,7 @@
|
||||
{% if results %}
|
||||
{% for video in results %}
|
||||
<div class="video-item {{ view_style }}">
|
||||
<a href="#player" data-src="/media/{{ video.source.media_url }}" data-thumb="/cache/{{ video.source.vid_thumb_url }}" data-title="{{ video.source.title }}" data-channel="{{ video.source.channel.channel_name }}" data-channel-id="{{ video.source.channel.channel_id }}" data-id="{{ video.source.youtube_id }}" onclick="createPlayer(this)">
|
||||
<a href="#player" data-id="{{ video.source.youtube_id }}" onclick="createPlayer(this)">
|
||||
<div class="video-thumb-wrap {{ view_style }}">
|
||||
<div class="video-thumb">
|
||||
<img src="/cache/{{ video.source.vid_thumb_url }}" alt="video-thumb">
|
||||
|
@ -45,7 +45,7 @@
|
||||
{% if results %}
|
||||
{% for video in results %}
|
||||
<div class="video-item {{ view_style }}">
|
||||
<a href="#player" data-src="/media/{{ video.source.media_url }}" data-thumb="/cache/{{ video.source.vid_thumb_url }}" data-title="{{ video.source.title }}" data-channel="{{ video.source.channel.channel_name }}" data-channel-id="{{ video.source.channel.channel_id }}" data-id="{{ video.source.youtube_id }}" onclick="createPlayer(this)">
|
||||
<a href="#player" data-id="{{ video.source.youtube_id }}" onclick="createPlayer(this)">
|
||||
<div class="video-thumb-wrap {{ view_style }}">
|
||||
<div class="video-thumb">
|
||||
<img src="/cache/{{ video.source.vid_thumb_url }}" alt="video-thumb">
|
||||
|
@ -87,7 +87,7 @@
|
||||
{% if results %}
|
||||
{% for video in results %}
|
||||
<div class="video-item {{ view_style }}">
|
||||
<a href="#player" data-src="/media/{{ video.source.media_url }}" data-thumb="/cache/{{ video.source.vid_thumb_url }}" data-title="{{ video.source.title }}" data-channel="{{ video.source.channel.channel_name }}" data-channel-id="{{ video.source.channel.channel_id }}" data-id="{{ video.source.youtube_id }}" onclick="createPlayer(this)">
|
||||
<a href="#player" data-id="{{ video.source.youtube_id }}" onclick="createPlayer(this)">
|
||||
<div class="video-thumb-wrap {{ view_style }}">
|
||||
<div class="video-thumb">
|
||||
<img src="/cache/{{ video.source.vid_thumb_url }}" alt="video-thumb">
|
||||
|
@ -6,7 +6,7 @@
|
||||
<video
|
||||
src="/media/{{ video.media_url }}"
|
||||
poster="/cache/{{ video.vid_thumb_url }}" controls preload="false"
|
||||
type='video/mp4' width="100%" playsinline id="video-item">
|
||||
type='video/mp4' width="100%" playsinline id="video-item" ontimeupdate="onVideoProgress('{{ video.youtube_id }}')" onloadedmetadata="setVideoProgress(0)">
|
||||
</video>
|
||||
</div>
|
||||
<div class="boxed-content">
|
||||
|
3
tubearchivist/static/.jshintrc
Normal file
3
tubearchivist/static/.jshintrc
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"esversion": 6
|
||||
}
|
@ -456,6 +456,17 @@ button:hover {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.player-stats {
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.player-stats span {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.video-desc-player {
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
@ -639,7 +650,7 @@ button:hover {
|
||||
filter: var(--img-filter);
|
||||
}
|
||||
|
||||
.thumb-icon.dislike img {
|
||||
.dislike {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
|
63
tubearchivist/static/img/icon-eye.svg
Normal file
63
tubearchivist/static/img/icon-eye.svg
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="500"
|
||||
height="500"
|
||||
viewBox="0 0 132.29197 132.29167"
|
||||
version="1.1"
|
||||
id="svg1303"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="Icons_seen.svg">
|
||||
<defs
|
||||
id="defs1297" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.0105705"
|
||||
inkscape:cx="84.208758"
|
||||
inkscape:cy="136.94831"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata1300">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-164.70764)">
|
||||
<path
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
d="M 66.145984,191.3255 A 71.797122,73.404487 0 0 0 2.5025987,230.88314 71.797122,73.404487 0 0 0 66.145984,270.38145 71.797122,73.404487 0 0 0 129.78937,230.82387 71.797122,73.404487 0 0 0 66.145984,191.3255 Z m -4.921549,7.22394 a 32.724755,32.724755 0 0 0 -13.334395,5.17759 12.828107,12.828107 0 0 1 2.180958,-0.18652 12.828107,12.828107 0 0 1 12.828141,12.82816 12.828107,12.828107 0 0 1 -12.828141,12.82822 12.828107,12.828107 0 0 1 -12.828192,-12.82822 12.828107,12.828107 0 0 1 0.04509,-0.91548 32.724755,32.724755 0 0 0 -3.86581,15.39964 32.724755,32.724755 0 0 0 27.161922,32.24981 A 59.09757,60.420619 0 0 1 13.7604,230.8774 59.09757,60.420619 0 0 1 61.224664,198.54948 Z m 10.482345,0.0563 a 59.09757,60.420619 0 0 1 46.82502,32.22523 59.09757,60.420619 0 0 1 -47.393377,32.32497 32.724755,32.724755 0 0 0 27.73169,-32.30187 32.724755,32.724755 0 0 0 -27.163333,-32.24833 z"
|
||||
id="path1091"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
@ -15,7 +15,7 @@
|
||||
version="1.1"
|
||||
id="svg1303"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="Icons_thumbs.svg">
|
||||
sodipodi:docname="icon_thumb.svg">
|
||||
<defs
|
||||
id="defs1297" />
|
||||
<sodipodi:namedview
|
||||
@ -25,18 +25,31 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.71458126"
|
||||
inkscape:cx="-133.80736"
|
||||
inkscape:cy="163.34297"
|
||||
inkscape:zoom="1.5046797"
|
||||
inkscape:cx="35.718548"
|
||||
inkscape:cy="203.39339"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-height="1009"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
inkscape:window-maximized="1"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true">
|
||||
<sodipodi:guide
|
||||
position="80.99058,65.965029"
|
||||
orientation="0,1"
|
||||
id="guide816"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="65.965178,49.107299"
|
||||
orientation="1,0"
|
||||
id="guide818"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata1300">
|
||||
<rdf:RDF>
|
||||
@ -55,8 +68,8 @@
|
||||
id="layer1"
|
||||
transform="translate(0,-164.70764)">
|
||||
<path
|
||||
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
d="m 74.762046,169.84647 c -0.757275,-0.0266 -1.556205,0.0266 -2.398918,0.17006 -17.977757,2.9811 5.863528,29.19697 -15.075776,44.15933 -17.503229,14.60104 -23.870308,10.01972 -24.044759,14.80451 v 47.00292 c 2.623747,6.94761 20.093043,14.05087 38.660635,15.56434 18.567588,1.51346 44.529822,-2.41107 44.816272,-10.49357 0.15245,-7.31882 -4.01785,-7.48655 -4.01785,-7.48655 0,0 9.14077,-0.56532 9.44575,-8.4939 0.15212,-7.77626 -8.85445,-8.88809 -8.85445,-8.88809 0,0 11.53636,-0.3275 11.53636,-8.34902 0,-8.20546 -8.87381,-8.85175 -11.6189,-8.99092 1.70324,-0.10363 8.42562,-2.42967 8.3861,-10.53741 -0.0399,-8.37053 -12.87508,-7.67987 -35.956784,-9.20144 2.66326,-15.52873 4.52035,-48.76031 -10.87768,-49.26032 z m -63.387663,53.22425 c -2.167221,0 -3.911718,1.45375 -3.911718,3.25977 v 53.07599 c 0,1.80609 1.744497,3.25983 3.911718,3.25983 h 14.602385 c 2.167228,0 3.911725,-1.45374 3.911725,-3.25983 v -53.07599 c 0,-1.80602 -1.744497,-3.25977 -3.911725,-3.25977 z"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
d="m 72.35681,178.12175 c -0.545876,-0.0192 -1.121779,0.0192 -1.729242,0.12259 -12.959134,2.14891 4.226681,21.04642 -10.867262,31.83193 -12.617074,10.52505 -17.206737,7.22264 -17.332488,10.67172 v 33.88171 c 1.891308,5.00813 14.483922,10.12847 27.868234,11.21944 13.384309,1.09096 32.098988,-1.73801 32.305468,-7.56421 0.10989,-5.27572 -2.896223,-5.39662 -2.896223,-5.39662 0,0 6.589043,-0.40752 6.808883,-6.12278 0.10966,-5.60545 -6.38265,-6.40691 -6.38265,-6.40691 0,0 8.31589,-0.23607 8.31589,-6.01832 0,-5.91485 -6.39662,-6.38072 -8.37539,-6.48104 1.22776,-0.0747 6.07353,-1.75141 6.04505,-7.59582 -0.0287,-6.03384 -9.280896,-5.53597 -25.919173,-6.63279 1.919791,-11.19377 3.258461,-35.14851 -7.841097,-35.50894 z m -45.69253,38.36631 c -1.562226,0 -2.819733,1.04793 -2.819733,2.34979 v 38.25943 c 0,1.30191 1.257507,2.34983 2.819733,2.34983 h 10.526021 c 1.562231,0 2.819739,-1.04792 2.819739,-2.34983 v -38.25943 c 0,-1.30186 -1.257508,-2.34979 -2.819739,-2.34979 z"
|
||||
id="rect1278"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.2 KiB |
@ -9,6 +9,7 @@ function sortChange(sortValue) {
|
||||
}
|
||||
|
||||
function isWatched(youtube_id) {
|
||||
// sendVideoProgress(youtube_id, 0); // Reset video progress on watched;
|
||||
var payload = JSON.stringify({'watched': youtube_id});
|
||||
sendPost(payload);
|
||||
var seenIcon = document.createElement('img');
|
||||
@ -33,6 +34,7 @@ function isWatchedButton(button) {
|
||||
}
|
||||
|
||||
function isUnwatched(youtube_id) {
|
||||
// sendVideoProgress(youtube_id, 0); // Reset video progress on unwatched;
|
||||
var payload = JSON.stringify({'un_watched': youtube_id});
|
||||
sendPost(payload);
|
||||
var unseenIcon = document.createElement('img');
|
||||
@ -188,7 +190,7 @@ function reEmbed() {
|
||||
|
||||
function dbBackup() {
|
||||
var payload = JSON.stringify({'db-backup': true});
|
||||
sendPost(payload)
|
||||
sendPost(payload);
|
||||
// clear button
|
||||
var message = document.createElement('p');
|
||||
message.innerText = 'backing up archive';
|
||||
@ -286,161 +288,266 @@ function cancelDelete() {
|
||||
|
||||
// player
|
||||
function createPlayer(button) {
|
||||
var mediaUrl = button.getAttribute('data-src');
|
||||
var mediaThumb = button.getAttribute('data-thumb');
|
||||
var mediaTitle = button.getAttribute('data-title');
|
||||
var mediaChannel = button.getAttribute('data-channel');
|
||||
var mediaChannelId = button.getAttribute('data-channel-id');
|
||||
var dataId = button.getAttribute('data-id');
|
||||
// get watched status
|
||||
var playedStatus = document.createDocumentFragment();
|
||||
playedStatus.appendChild(document.getElementById(dataId));
|
||||
// create player
|
||||
removePlayer();
|
||||
var playerElement = document.createElement('div');
|
||||
playerElement.classList.add("video-player");
|
||||
// var playerElement = document.getElementById('player');
|
||||
playerElement.setAttribute('data-id', dataId);
|
||||
// playerElement.innerHTML = '';
|
||||
var videoPlayer = document.createElement('video');
|
||||
videoPlayer.setAttribute('src', mediaUrl);
|
||||
videoPlayer.setAttribute('controls', true);
|
||||
videoPlayer.setAttribute('autoplay', true);
|
||||
videoPlayer.setAttribute('width', '100%');
|
||||
videoPlayer.setAttribute('playsinline', true);
|
||||
videoPlayer.setAttribute('poster', mediaThumb);
|
||||
videoPlayer.setAttribute('id', 'video-item'); // Set ID to get URL for casting
|
||||
playerElement.appendChild(videoPlayer);
|
||||
// title bar
|
||||
var titleBar = document.createElement('div');
|
||||
titleBar.classList.add('player-title', 'boxed-content');
|
||||
// close
|
||||
var closeButton = document.createElement('img');
|
||||
closeButton.className = 'close-button';
|
||||
closeButton.setAttribute('src', "/static/img/icon-close.svg");
|
||||
closeButton.setAttribute('alt', 'close-icon');
|
||||
closeButton.setAttribute('data', dataId);
|
||||
closeButton.setAttribute('onclick', "removePlayer()");
|
||||
closeButton.setAttribute('title', 'Close player');
|
||||
titleBar.appendChild(closeButton);
|
||||
// played
|
||||
titleBar.appendChild(playedStatus);
|
||||
// channel title
|
||||
var channelTitleLink = document.createElement('a');
|
||||
channelTitleLink.setAttribute('href', '/channel/' + mediaChannelId + '/');
|
||||
var channelTitle = document.createElement('h3');
|
||||
channelTitle.innerText = mediaChannel;
|
||||
channelTitleLink.appendChild(channelTitle);
|
||||
titleBar.appendChild(channelTitleLink);
|
||||
// video title
|
||||
var videoTitleLink = document.createElement('a');
|
||||
videoTitleLink.setAttribute('href', '/video/' + dataId + '/');
|
||||
var videoTitle = document.createElement('h2');
|
||||
videoTitle.setAttribute('id', "video-title"); // Set ID to get title for casting
|
||||
videoTitle.innerText = mediaTitle;
|
||||
var castScript = document.getElementById('cast-script'); // Get cast-script
|
||||
if(typeof(castScript) != 'undefined' && castScript != null) { // Check if cast integration is enabled
|
||||
var castButton = document.createElement("google-cast-launcher"); // Create cast button
|
||||
castButton.setAttribute('id', "castbutton"); // Set ID to apply theme
|
||||
titleBar.appendChild(castButton); // Add cast button to title
|
||||
var videoId = button.getAttribute('data-id');
|
||||
var videoData = getVideoData(videoId);
|
||||
var videoUrl = videoData.media_url;
|
||||
var videoThumbUrl = videoData.vid_thumb_url;
|
||||
var videoName = videoData.title;
|
||||
|
||||
var playlist = '';
|
||||
var videoPlaylists = videoData.playlist; // Array of playlists the video is in
|
||||
if (typeof(videoPlaylists) != 'undefined') {
|
||||
var subbedPlaylists = getSubbedPlaylists(videoPlaylists); // Array of playlist the video is in that are subscribed
|
||||
if (subbedPlaylists.length != 0) {
|
||||
var playlistData = getPlaylistData(subbedPlaylists[0]); // Playlist data for first subscribed playlist
|
||||
var playlistId = playlistData.playlist_id;
|
||||
var playlistName = playlistData.playlist_name;
|
||||
var playlist = `<h5><a href="/playlist/${playlistId}/">${playlistName}</a></h5>`;
|
||||
}
|
||||
videoTitleLink.appendChild(videoTitle);
|
||||
titleBar.appendChild(videoTitleLink);
|
||||
// add titlebar
|
||||
playerElement.appendChild(titleBar);
|
||||
// add whole
|
||||
document.getElementById("player").appendChild(playerElement);
|
||||
}
|
||||
|
||||
var videoProgress = videoData.player.progress; // Groundwork for saving video position, change once progress variable is added to API
|
||||
var videoViews = formatNumbers(videoData.stats.view_count);
|
||||
|
||||
var channelId = videoData.channel.channel_id;
|
||||
var channelName = videoData.channel.channel_name;
|
||||
|
||||
removePlayer();
|
||||
document.getElementById(videoId).outerHTML = ''; // Remove watch indicator from video info
|
||||
|
||||
// If cast integration is enabled create cast button
|
||||
var castButton = ``;
|
||||
var castScript = document.getElementById('cast-script');
|
||||
if (typeof(castScript) != 'undefined' && castScript != null) {
|
||||
var castButton = `<google-cast-launcher id="castbutton"></google-cast-launcher>`;
|
||||
}
|
||||
|
||||
// Watched indicator
|
||||
if (videoData.player.is_watched) {
|
||||
var playerState = "seen";
|
||||
var watchedFunction = "Unwatched";
|
||||
} else {
|
||||
var playerState = "unseen";
|
||||
var watchedFunction = "Watched";
|
||||
}
|
||||
|
||||
var playerStats = `<div class="thumb-icon player-stats"><img src="/static/img/icon-eye.svg" alt="views icon"><span>${videoViews}</span>`;
|
||||
if (videoData.stats.like_count) {
|
||||
var likes = formatNumbers(videoData.stats.like_count);
|
||||
playerStats += `<span>|</span><img src="/static/img/icon-thumb.svg" alt="thumbs-up"><span>${likes}</span>`;
|
||||
}
|
||||
if (videoData.stats.dislike_count) {
|
||||
var dislikes = formatNumbers(videoData.stats.dislike_count);
|
||||
playerStats += `<span>|</span><img class="dislike" src="/static/img/icon-thumb.svg" alt="thumbs-down"><span>${dislikes}</span>`;
|
||||
}
|
||||
playerStats += "</div>";
|
||||
|
||||
const markup = `
|
||||
<div class="video-player" data-id="${videoId}">
|
||||
<video src="${videoUrl}#t=${videoProgress}" poster="${videoThumbUrl}" ontimeupdate="onVideoProgress('${videoId}')" controls autoplay type='video/mp4' width="100%" playsinline id="video-item"></video>
|
||||
<div class="player-title boxed-content">
|
||||
<img class="close-button" src="/static/img/icon-close.svg" alt="close-icon" data="${videoId}" onclick="removePlayer()" title="Close player">
|
||||
<img src="/static/img/icon-${playerState}.svg" alt="${playerState}-icon" id="${videoId}" onclick="is${watchedFunction}(this.id)" class="${playerState}-icon" title="Mark as ${watchedFunction}">
|
||||
${castButton}
|
||||
${playerStats}
|
||||
<div class="player-channel-playlist">
|
||||
<h3><a href="/channel/${channelId}/">${channelName}</a></h3>
|
||||
${playlist}
|
||||
</div>
|
||||
<a href="/video/${videoId}/"><h2 id="video-title">${videoName}</h2></a>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
const divPlayer = document.getElementById("player");
|
||||
divPlayer.innerHTML = markup;
|
||||
}
|
||||
|
||||
// Set video progress in seconds
|
||||
function setVideoProgress(videoProgress) {
|
||||
if (isNaN(videoProgress)) {
|
||||
videoProgress = 0;
|
||||
}
|
||||
var videoElement = document.getElementById("video-item");
|
||||
videoElement.currentTime = videoProgress;
|
||||
}
|
||||
|
||||
// Runs on video playback, marks video as watched if video gets to 90% or higher, WIP sends position to api
|
||||
function onVideoProgress(videoId) {
|
||||
var videoElement = document.getElementById("video-item");
|
||||
if (videoElement != null) {
|
||||
if ((videoElement.currentTime % 10).toFixed(1) <= 0.2) { // Check progress every 10 seconds or else progress is checked a few times a second
|
||||
// sendVideoProgress(videoId, videoElement.currentTime); // Groundwork for saving video position
|
||||
if ((videoElement.currentTime / videoElement.duration) >= 0.90) {
|
||||
isWatched(videoId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Groundwork for saving video position
|
||||
function sendVideoProgress(videoId, videoProgress) {
|
||||
var apiEndpoint = "/api/video/";
|
||||
if (isNaN(videoProgress)) {
|
||||
videoProgress = 0;
|
||||
}
|
||||
var data = {
|
||||
"data": [{
|
||||
"youtube_id": videoId,
|
||||
"player": {
|
||||
"progress": videoProgress
|
||||
}
|
||||
}]
|
||||
};
|
||||
videoData = apiRequest(apiEndpoint, "POST", data);
|
||||
}
|
||||
|
||||
// Format numbers for frontend
|
||||
function formatNumbers(number) {
|
||||
var numberUnformatted = parseFloat(number);
|
||||
if (numberUnformatted > 999999999) {
|
||||
var numberFormatted = (numberUnformatted / 1000000000).toFixed(1).toString() + "B";
|
||||
} else if (numberUnformatted > 999999) {
|
||||
var numberFormatted = (numberUnformatted / 1000000).toFixed(1).toString() + "M";
|
||||
} else if (numberUnformatted > 999) {
|
||||
var numberFormatted = (numberUnformatted / 1000).toFixed(1).toString() + "K";
|
||||
} else {
|
||||
var numberFormatted = numberUnformatted;
|
||||
}
|
||||
return numberFormatted;
|
||||
}
|
||||
|
||||
// Gets video data in JSON format when passed video ID
|
||||
function getVideoData(videoId) {
|
||||
var apiEndpoint = "/api/video/" + videoId + "/";
|
||||
videoData = apiRequest(apiEndpoint, "GET");
|
||||
return videoData.data;
|
||||
}
|
||||
|
||||
// Gets channel data in JSON format when passed channel ID
|
||||
function getChannelData(channelId) {
|
||||
var apiEndpoint = "/api/channel/" + channelId + "/";
|
||||
channelData = apiRequest(apiEndpoint, "GET");
|
||||
return channelData.data;
|
||||
}
|
||||
|
||||
// Gets playlist data in JSON format when passed playlist ID
|
||||
function getPlaylistData(playlistId) {
|
||||
var apiEndpoint = "/api/playlist/" + playlistId + "/";
|
||||
playlistData = apiRequest(apiEndpoint, "GET");
|
||||
return playlistData.data;
|
||||
}
|
||||
|
||||
// Given an array of playlist ids it returns an array of subbed playlist ids from that list
|
||||
function getSubbedPlaylists(videoPlaylists) {
|
||||
var subbedPlaylists = [];
|
||||
for (var i = 0; i < videoPlaylists.length; i++) {
|
||||
if(getPlaylistData(videoPlaylists[i]).playlist_subscribed) {
|
||||
subbedPlaylists.push(videoPlaylists[i]);
|
||||
}
|
||||
}
|
||||
return subbedPlaylists;
|
||||
}
|
||||
|
||||
// Makes api requests when passed an endpoint and method ("GET" or "POST")
|
||||
function apiRequest(apiEndpoint, method, data) {
|
||||
const xhttp = new XMLHttpRequest();
|
||||
var sessionToken = getCookie("sessionid");
|
||||
xhttp.open(method, apiEndpoint, false);
|
||||
xhttp.setRequestHeader("Authorization", "Token " + sessionToken);
|
||||
xhttp.setRequestHeader("Content-Type", "application/json");
|
||||
xhttp.send(JSON.stringify(data));
|
||||
return JSON.parse(xhttp.responseText);
|
||||
}
|
||||
|
||||
function removePlayer() {
|
||||
var playerElement = document.getElementById('player');
|
||||
if (playerElement.hasChildNodes()) {
|
||||
var youtubeId = playerElement.childNodes[0].getAttribute("data-id");
|
||||
var youtubeId = playerElement.childNodes[1].getAttribute("data-id");
|
||||
var playedStatus = document.createDocumentFragment();
|
||||
var playedBox = document.getElementById(youtubeId);
|
||||
if (playedBox) {
|
||||
playedStatus.appendChild(playedBox);
|
||||
};
|
||||
}
|
||||
playerElement.innerHTML = '';
|
||||
// append played status
|
||||
var videoInfo = document.getElementById('video-info-' + youtubeId);
|
||||
videoInfo.insertBefore(playedStatus, videoInfo.firstChild);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// multi search form
|
||||
function searchMulti(query) {
|
||||
if (query.length > 1) {
|
||||
var payload = JSON.stringify({'multi_search': query})
|
||||
var payload = JSON.stringify({'multi_search': query});
|
||||
var http = new XMLHttpRequest();
|
||||
http.onreadystatechange = function() {
|
||||
if (http.readyState === 4) {
|
||||
allResults = JSON.parse(http.response)['results'];
|
||||
allResults = JSON.parse(http.response).results;
|
||||
populateMultiSearchResults(allResults);
|
||||
};
|
||||
}
|
||||
};
|
||||
http.open("POST", "/process/", true);
|
||||
http.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
|
||||
http.setRequestHeader("Content-type", "application/json");
|
||||
http.send(payload);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getViewDefaults(view) {
|
||||
var defaultView = document.getElementById("id_" + view).value;
|
||||
return defaultView
|
||||
return defaultView;
|
||||
}
|
||||
|
||||
function populateMultiSearchResults(allResults) {
|
||||
// videos
|
||||
var defaultVideo = getViewDefaults("home");
|
||||
var allVideos = allResults["video_results"];
|
||||
var allVideos = allResults.video_results;
|
||||
var videoBox = document.getElementById("video-results");
|
||||
videoBox.innerHTML = "";
|
||||
for (let index = 0; index < allVideos.length; index++) {
|
||||
const video = allVideos[index]["source"];
|
||||
const video = allVideos[index].source;
|
||||
const videoDiv = createVideo(video, defaultVideo);
|
||||
videoBox.appendChild(videoDiv);
|
||||
};
|
||||
}
|
||||
// channels
|
||||
var defaultChannel = getViewDefaults("channel");
|
||||
var allChannels = allResults["channel_results"];
|
||||
var allChannels = allResults.channel_results;
|
||||
var channelBox = document.getElementById("channel-results");
|
||||
channelBox.innerHTML = "";
|
||||
for (let index = 0; index < allChannels.length; index++) {
|
||||
const channel = allChannels[index]["source"];
|
||||
const channel = allChannels[index].source;
|
||||
const channelDiv = createChannel(channel, defaultChannel);
|
||||
channelBox.appendChild(channelDiv);
|
||||
};
|
||||
}
|
||||
// playlists
|
||||
var defaultPlaylist = getViewDefaults("playlist");
|
||||
var allPlaylists = allResults["playlist_results"];
|
||||
var allPlaylists = allResults.playlist_results;
|
||||
var playlistBox = document.getElementById("playlist-results");
|
||||
playlistBox.innerHTML = "";
|
||||
for (let index = 0; index < allPlaylists.length; index++) {
|
||||
const playlist = allPlaylists[index]["source"];
|
||||
const playlist = allPlaylists[index].source;
|
||||
const playlistDiv = createPlaylist(playlist, defaultPlaylist);
|
||||
playlistBox.appendChild(playlistDiv);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function createVideo(video, viewStyle) {
|
||||
// create video item div from template
|
||||
const videoId = video["youtube_id"];
|
||||
const mediaUrl = video["media_url"];
|
||||
const thumbUrl = "/cache/" + video["vid_thumb_url"];
|
||||
const videoTitle = video["title"];
|
||||
const videoPublished = video["published"];
|
||||
const videoDuration = video["player"]["duration_str"];
|
||||
if (video["player"]["watched"]) {
|
||||
const videoId = video.youtube_id;
|
||||
const mediaUrl = video.media_url;
|
||||
const thumbUrl = "/cache/" + video.vid_thumb_url;
|
||||
const videoTitle = video.title;
|
||||
const videoPublished = video.published;
|
||||
const videoDuration = video.player.duration_str;
|
||||
if (video.player.watched) {
|
||||
var playerState = "seen";
|
||||
} else {
|
||||
var playerState = "unseen";
|
||||
};
|
||||
const channelId = video["channel"]["channel_id"];
|
||||
const channelName = video["channel"]["channel_name"];
|
||||
const channelId = video.channel.channel_id;
|
||||
const channelName = video.channel.channel_name;
|
||||
// build markup
|
||||
const markup = `
|
||||
<a href="#player" data-src="/media/${mediaUrl}" data-thumb="${thumbUrl}" data-title="${videoTitle}" data-channel="${channelName}" data-channel-id="${channelId}" data-id="${videoId}" onclick="createPlayer(this)">
|
||||
@ -463,25 +570,25 @@ function createVideo(video, viewStyle) {
|
||||
<a class="video-more" href="/video/${videoId}/"><h2>${videoTitle}</h2></a>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
`;
|
||||
const videoDiv = document.createElement("div");
|
||||
videoDiv.setAttribute("class", "video-item " + viewStyle);
|
||||
videoDiv.innerHTML = markup
|
||||
return videoDiv
|
||||
videoDiv.innerHTML = markup;
|
||||
return videoDiv;
|
||||
}
|
||||
|
||||
|
||||
function createChannel(channel, viewStyle) {
|
||||
// create channel item div from template
|
||||
const channelId = channel["channel_id"];
|
||||
const channelName = channel["channel_name"];
|
||||
const channelSubs = channel["channel_subs"];
|
||||
const channelLastRefresh = channel["channel_last_refresh"];
|
||||
if (channel["channel_subscribed"]) {
|
||||
var button = `<button class="unsubscribe" type="button" id="${channelId}" onclick="unsubscribe(this.id)" title="Unsubscribe from ${channelName}">Unsubscribe</button>`
|
||||
const channelId = channel.channel_id;
|
||||
const channelName = channel.channel_name;
|
||||
const channelSubs = channel.channel_subs;
|
||||
const channelLastRefresh = channel.channel_last_refresh;
|
||||
if (channel.channel_subscribed) {
|
||||
var button = `<button class="unsubscribe" type="button" id="${channelId}" onclick="unsubscribe(this.id)" title="Unsubscribe from ${channelName}">Unsubscribe</button>`;
|
||||
} else {
|
||||
var button = `<button type="button" id="${channelId}" onclick="subscribe(this.id)" title="Subscribe to ${channelName}">Subscribe</button>`
|
||||
};
|
||||
var button = `<button type="button" id="${channelId}" onclick="subscribe(this.id)" title="Subscribe to ${channelName}">Subscribe</button>`;
|
||||
}
|
||||
// build markup
|
||||
const markup = `
|
||||
<div class="channel-banner ${viewStyle}">
|
||||
@ -508,25 +615,25 @@ function createChannel(channel, viewStyle) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
`;
|
||||
const channelDiv = document.createElement("div");
|
||||
channelDiv.setAttribute("class", "channel-item " + viewStyle);
|
||||
channelDiv.innerHTML = markup;
|
||||
return channelDiv
|
||||
return channelDiv;
|
||||
}
|
||||
|
||||
function createPlaylist(playlist, viewStyle) {
|
||||
// create playlist item div from template
|
||||
const playlistId = playlist["playlist_id"];
|
||||
const playlistName = playlist["playlist_name"];
|
||||
const playlistChannelId = playlist["playlist_channel_id"];
|
||||
const playlistChannel = playlist["playlist_channel"];
|
||||
const playlistLastRefresh = playlist["playlist_last_refresh"];
|
||||
if (playlist["playlist_subscribed"]) {
|
||||
var button = `<button class="unsubscribe" type="button" id="${playlistId}" onclick="unsubscribe(this.id)" title="Unsubscribe from ${playlistName}">Unsubscribe</button>`
|
||||
const playlistId = playlist.playlist_id;
|
||||
const playlistName = playlist.playlist_name;
|
||||
const playlistChannelId = playlist.playlist_channel_id;
|
||||
const playlistChannel = playlist.playlist_channel;
|
||||
const playlistLastRefresh = playlist.playlist_last_refresh;
|
||||
if (playlist.playlist_subscribed) {
|
||||
var button = `<button class="unsubscribe" type="button" id="${playlistId}" onclick="unsubscribe(this.id)" title="Unsubscribe from ${playlistName}">Unsubscribe</button>`;
|
||||
} else {
|
||||
var button = `<button type="button" id="${playlistId}" onclick="subscribe(this.id)" title="Subscribe to ${playlistName}">Subscribe</button>`
|
||||
};
|
||||
var button = `<button type="button" id="${playlistId}" onclick="subscribe(this.id)" title="Subscribe to ${playlistName}">Subscribe</button>`;
|
||||
}
|
||||
const markup = `
|
||||
<div class="playlist-thumbnail">
|
||||
<a href="/playlist/${playlistId}/">
|
||||
@ -539,11 +646,11 @@ function createPlaylist(playlist, viewStyle) {
|
||||
<p>Last refreshed: ${playlistLastRefresh}</p>
|
||||
${button}
|
||||
</div>
|
||||
`
|
||||
`;
|
||||
const playlistDiv = document.createElement("div");
|
||||
playlistDiv.setAttribute("class", "playlist-item " + viewStyle);
|
||||
playlistDiv.innerHTML = markup;
|
||||
return playlistDiv
|
||||
return playlistDiv;
|
||||
}
|
||||
|
||||
|
||||
@ -565,8 +672,8 @@ function getCookie(c_name) {
|
||||
c_end = document.cookie.indexOf(";", c_start);
|
||||
if (c_end == -1) c_end = document.cookie.length;
|
||||
return unescape(document.cookie.substring(c_start,c_end));
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -582,17 +689,17 @@ function textReveal() {
|
||||
} else {
|
||||
textBox.style.height = 'unset';
|
||||
button.innerText = 'Hide';
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function showForm() {
|
||||
var formElement = document.getElementById('hidden-form');
|
||||
var displayStyle = formElement.style.display
|
||||
var displayStyle = formElement.style.display;
|
||||
if (displayStyle === "") {
|
||||
formElement.style.display = 'block';
|
||||
} else {
|
||||
formElement.style.display = "";
|
||||
};
|
||||
}
|
||||
animate('animate-icon', 'pulse-img');
|
||||
}
|
||||
|
||||
@ -602,5 +709,5 @@ function animate(elementId, animationClass) {
|
||||
toAnimate.className = animationClass;
|
||||
} else {
|
||||
toAnimate.classList.remove(animationClass);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user