summaryrefslogtreecommitdiff
path: root/pages/together.inc
diff options
context:
space:
mode:
authorMinteck <contact@minteck.org>2023-02-23 19:34:56 +0100
committerMinteck <contact@minteck.org>2023-02-23 19:34:56 +0100
commit3d1cd02f27518f1a04374c7c8320cd5d82ede6e9 (patch)
tree75be5fba4368472fb11c8015aee026b2b9a71888 /pages/together.inc
parent8cc1f13c17fa2fb5a4410542d39e650e02945634 (diff)
downloadpluralconnect-3d1cd02f27518f1a04374c7c8320cd5d82ede6e9.tar.gz
pluralconnect-3d1cd02f27518f1a04374c7c8320cd5d82ede6e9.tar.bz2
pluralconnect-3d1cd02f27518f1a04374c7c8320cd5d82ede6e9.zip
Updated 40 files, added 37 files, deleted 1103 files and renamed 3905 files (automated)
Diffstat (limited to 'pages/together.inc')
-rw-r--r--pages/together.inc940
1 files changed, 0 insertions, 940 deletions
diff --git a/pages/together.inc b/pages/together.inc
deleted file mode 100644
index c210fa5..0000000
--- a/pages/together.inc
+++ /dev/null
@@ -1,940 +0,0 @@
-<?php
-
-$_GET['old'] = "";
-require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages;
-require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
-
-global $WebSocketAddress;
-
-if (!isset($WebSocketAddress)) {
- $WebSocketAddress = "wss://ponies.equestria.horse/_WatchTogether-WebSocket-EntryPoint/socket";
-}
-
-?>
-
-<style>
- .list-group-item {
- color: #fff;
- background-color: #222;
- border: 1px solid rgba(255, 255, 255, .125);
- }
-
- .list-group-item.disabled {
- color: #fff;
- background-color: #222;
- border-color: rgba(255, 255, 255, .125);
- opacity: .75;
- }
-
- .list-group-item-action:hover {
- background-color: #252525;
- color: #ddd;
- }
-
- .list-group-item-action:active, .list-group-item-action:focus {
- background-color: #272727;
- color: #bbb;
- }
-
- .video-queue-item {
- display: grid;
- grid-template-columns: 1fr max-content;
- grid-gap: 10px;
- cursor: pointer;
- }
-
- .video-queue-item-status {
- filter: invert(1);
- display: block;
- height: 32px;
- width: 32px;
- }
-
- .video-queue-item-part {
- display: flex;
- align-items: center;
- }
-
- .video-queue-item-metadata {
- width: 100%;
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
- }
-
- .video-queue-item-title-outer, .video-queue-item-author-outer {
- display: flex;
- align-items: center;
- }
-
- .video-queue-item-title, .video-queue-item-title-outer, .video-queue-item-author, .video-queue-item-author-outer {
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
- width: 100%;
- }
-
- .modal-header {
- border-bottom: 1px solid #353738;
- }
-
- .modal-content {
- border: 1px solid rgba(255, 255, 255, .2);
- background-color: #111;
- }
-
- .btn-close {
- filter: invert(1);
- }
-
- .user-ping {
- float: right;
- display: inline-block;
- width: 16px;
- height: 16px;
- border-radius: 999px;
- position: relative;
- top: 5px;
- }
-
- .control-item {
- display: inline-block;
- cursor: pointer;
- border-radius: 999px;
- background-color: rgba(0, 0, 0, 0);
- border: 1px solid rgba(255, 255, 255, 0);
- transition: background-color 200ms, border-color 200ms;
- }
-
- .control-item:hover {
- background-color: rgba(0, 0, 0, .25);
- border-color: rgba(255, 255, 255, .1);
- }
-
- .control-item:active {
- background-color: rgba(0, 0, 0, .5);
- border-color: rgba(255, 255, 255, .25);
- }
-
- .control-icon {
- filter: invert(1);
- width: 24px;
- height: 24px;
- margin: 12px;
- pointer-events: none;
- }
-
- body.hide-controls * {
- cursor: none;
- }
-
- #controls-outer {
- opacity: 1;
- transition: opacity 500ms;
- }
-
- .navbar, #sidebar {
- opacity: 1;
- transition: opacity 500ms;
- }
-
- body.hide-controls #controls-outer {
- opacity: 0;
- }
-
- body.hide-controls .navbar, body.hide-controls #sidebar {
- opacity: .25;
- }
-
- body.fullscreen #app-container {
- grid-template-columns: 1fr !important;
- }
-
- body.fullscreen .navbar, body.fullscreen #sidebar {
- display: none;
- }
-
- body.fullscreen #app-container div, body.fullscreen #app-container video {
- height: 100vh !important;
- }
-
- body.fullscreen #controls-outer, body.fullscreen #notification {
- inset: 0 !important;
- }
-
- #notification {
- opacity: 0;
- pointer-events: none;
- transition: opacity 200ms;
- }
-
- #video-title {
- opacity: 1;
- transition: opacity 200ms;
- }
-
- body.notification #notification {
- opacity: 1;
- }
-
- body.notification #video-title {
- opacity: 0;
- }
-
- body.skipper #skipper {
- opacity: 1 !important;
- pointer-events: initial !important;
- }
-
- #skipper {
- opacity: 0;
- pointer-events: none;
- transition: opacity 200ms;
- position: fixed;
- bottom: 79px;
- z-index: 999;
- background: rgba(0, 0, 0, .5);
- border-radius: 10px;
- padding: 10px 20px;
- left: 20px;
- border: 1px solid rgba(255, 255, 255, .25);
- cursor: pointer;
- }
-
- #skipper:hover {
- background: rgba(0, 0, 0, .75) !important;
- }
-
- #skipper:active {
- background: rgba(0, 0, 0, 1) !important;
- }
-</style>
-
-<script src="/assets/editor/thing.js"></script>
-
-<div class="modal fade" id="error" data-bs-backdrop="static" data-bs-keyboard="false" style="z-index: 99999;">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <h4 class="modal-title">An error occurred</h4>
- </div>
-
- <div class="modal-body">
- <div class="alert alert-danger" id="error-message"></div>
- </div>
- </div>
- </div>
-</div>
-
-<div class="modal fade" id="add" data-bs-backdrop="static" data-bs-keyboard="false">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <h4 class="modal-title">Add new video</h4>
- </div>
-
- <div class="modal-body">
- <p>Enter a YouTube video ID to add to the queue:</p>
- <input type="text" class="form-control" id="add-id" placeholder="e.g. K9tUKbOFots" style="color:white;background:#111;border-color:#222;">
- <p style="margin-top:10px;margin-bottom: 0;">
- <div class="btn-group">
- <span onclick="doAdd();" id="add-btn-yes" class="btn btn-primary">Add</span>
- <span onclick="closeAdd();" id="add-btn-no" class="btn btn-secondary">Cancel</span>
- </div>
- <a href="#" onclick="document.getElementById('add-id').value = 'K9tUKbOFots';">test</a>
- </p>
- </div>
- </div>
- </div>
-</div>
-
-<div class="modal fade" id="welcome" data-bs-backdrop="static" data-bs-keyboard="false">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <h4 class="modal-title">Welcome to Watch Together!</h4>
- </div>
-
- <div class="modal-body">
- <h5>Host a new session</h5>
- <p>You will be given an invite code to share with your partner·s.</p>
- <span class="btn btn-primary" id="host-start" onclick="hostSession();">Start</span>
-
- <hr>
-
- <h5>Join an existing session</h5>
- <p>Enter the invite code your partner has given you:</p>
- <div style="display:grid;grid-template-columns: repeat(8, 1fr);grid-gap:10px;">
- <input type="text" class="form-control" id="invite-input-1" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1">
- <input type="text" class="form-control" id="invite-input-2" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1">
- <input type="text" class="form-control" id="invite-input-3" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1">
- <input type="text" class="form-control" id="invite-input-4" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1">
- <input type="text" class="form-control" id="invite-input-5" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1">
- <input type="text" class="form-control" id="invite-input-6" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1">
- <input type="text" class="form-control" id="invite-input-7" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1">
- <input type="text" class="form-control" id="invite-input-8" style="text-align: center;color:white;background:#111;border-color:#222;" onchange="processInviteCode(event);" onkeydown="processInviteCode(event);" onkeyup="processInviteCode(event);" maxlength="1">
- </div>
- </div>
- </div>
- </div>
-</div>
-<script>
- document.getElementById("invite-input-1").disabled = true;
- document.getElementById("invite-input-2").disabled = true;
- document.getElementById("invite-input-3").disabled = true;
- document.getElementById("invite-input-4").disabled = true;
- document.getElementById("invite-input-5").disabled = true;
- document.getElementById("invite-input-6").disabled = true;
- document.getElementById("invite-input-7").disabled = true;
- document.getElementById("invite-input-8").disabled = true;
- document.getElementById("host-start").classList.add("disabled");
-
- let modal = new bootstrap.Modal(document.getElementById('welcome'));
- modal.show();
- document.getElementById("invite-input-1").focus();
-
- window.modalAdd = new bootstrap.Modal(document.getElementById('add'));
-
- function openAdd() {
- modalAdd.show();
- }
-
- function closeAdd() {
- document.getElementById("add-id").value = "";
- modalAdd.hide();
- }
-
- function doAdd() {
- document.getElementById("add-id").disabled = true;
- document.getElementById("add-btn-yes").classList.add("disabled");
- document.getElementById("add-btn-no").classList.add("disabled");
-
- socket.send(JSON.stringify({
- task: "UPDATE_QUEUE",
- payload: {
- operation: "+",
- video: document.getElementById("add-id").value
- }
- }))
- }
-
- function toPrettyTime(seconds) {
- let parts = new Date(seconds * 1000).toUTCString().split(" ")[4].split(":");
- parts[0] = parseInt(parts[0]).toString();
-
- if (parts[0] === "0") {
- parts[1] = parseInt(parts[1]).toString();
- parts.shift();
- }
-
- return parts.join(":");
- }
-
- function processInviteCode(event) {
- let i1 = document.getElementById("invite-input-1").value.trim().toLowerCase().replace(/[^\da-z]+/gm, "");
- let i2 = document.getElementById("invite-input-2").value.trim().toLowerCase().replace(/[^\da-z]+/gm, "");
- let i3 = document.getElementById("invite-input-3").value.trim().toLowerCase().replace(/[^\da-z]+/gm, "");
- let i4 = document.getElementById("invite-input-4").value.trim().toLowerCase().replace(/[^\da-z]+/gm, "");
- let i5 = document.getElementById("invite-input-5").value.trim().toLowerCase().replace(/[^\da-z]+/gm, "");
- let i6 = document.getElementById("invite-input-6").value.trim().toLowerCase().replace(/[^\da-z]+/gm, "");
- let i7 = document.getElementById("invite-input-7").value.trim().toLowerCase().replace(/[^\da-z]+/gm, "");
- let i8 = document.getElementById("invite-input-8").value.trim().toLowerCase().replace(/[^\da-z]+/gm, "");
-
- document.getElementById("invite-input-1").value = i1;
- document.getElementById("invite-input-2").value = i2;
- document.getElementById("invite-input-3").value = i3;
- document.getElementById("invite-input-4").value = i4;
- document.getElementById("invite-input-5").value = i5;
- document.getElementById("invite-input-6").value = i6;
- document.getElementById("invite-input-7").value = i7;
- document.getElementById("invite-input-8").value = i8;
-
- if (i8 === "") {
- document.getElementById("invite-input-8").focus();
- }
- if (i7 === "") {
- document.getElementById("invite-input-7").focus();
- }
- if (i6 === "") {
- document.getElementById("invite-input-6").focus();
- }
- if (i5 === "") {
- document.getElementById("invite-input-5").focus();
- }
- if (i4 === "") {
- document.getElementById("invite-input-4").focus();
- }
- if (i3 === "") {
- document.getElementById("invite-input-3").focus();
- }
- if (i2 === "") {
- document.getElementById("invite-input-2").focus();
- }
- if (i1 === "") {
- document.getElementById("invite-input-1").focus();
- }
-
- if (event instanceof KeyboardEvent) {
- if (event.code === "Backspace" && event.type === "keydown") {
- let el = event.target;
- let ep = document.getElementById("invite-input-" + (el['id'].split("-")[2] - 1));
-
- if (ep !== null) {
- if (el.value.trim() === "") {
- ep.value = "";
- ep.focus();
- } else {
- el.value = "";
- ep.focus();
- }
- }
- }
- }
-
- if (i1.length === 1 && i2.length === 1 && i3.length === 1 && i4.length === 1 && i5.length === 1 && i6.length === 1 && i7.length === 1 && i8.length === 1 && ((event.type && event.type === "keyup") || !event.type)) {
- joinSession(i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8);
- }
- }
-
- async function joinSession(code) {
- document.getElementById("invite-input-1").disabled = true;
- document.getElementById("invite-input-2").disabled = true;
- document.getElementById("invite-input-3").disabled = true;
- document.getElementById("invite-input-4").disabled = true;
- document.getElementById("invite-input-5").disabled = true;
- document.getElementById("invite-input-6").disabled = true;
- document.getElementById("invite-input-7").disabled = true;
- document.getElementById("invite-input-8").disabled = true;
- document.getElementById("host-start").classList.add("disabled");
-
- window.inviteCode = code;
-
- startSession();
- }
-
- async function hostSession() {
- document.getElementById("invite-input-1").disabled = true;
- document.getElementById("invite-input-2").disabled = true;
- document.getElementById("invite-input-3").disabled = true;
- document.getElementById("invite-input-4").disabled = true;
- document.getElementById("invite-input-5").disabled = true;
- document.getElementById("invite-input-6").disabled = true;
- document.getElementById("invite-input-7").disabled = true;
- document.getElementById("invite-input-8").disabled = true;
- document.getElementById("host-start").classList.add("disabled");
-
- window.inviteCode = null;
-
- startSession();
- }
-
- window.terminated = false;
- window.users = null;
- window.queue = null;
- window.segments = [];
- window.originalTitle = document.title;
-
- async function connect() {
- window.identity = JSON.parse(await (await window.fetch("/api/me")).text());
- window.sessionToken = await (await window.fetch("/api/token")).text();
-
- window.socket = new WebSocket("<?= $WebSocketAddress ?>");
-
- socket.onclose = (event) => {
- console.log("[ws:close] ",event);
-
- if (window.terminated) {
- modal.hide();
- return;
- }
-
- if (event.wasClean) {
- document.getElementById('error-message').innerText = "Connection closed";
- } else {
- if (event.reason) {
- document.getElementById('error-message').innerText = "Connection closed unexpectedly with code " + event.code + ": " + event.reason;
- } else {
- document.getElementById('error-message').innerText = "Connection closed unexpectedly with code " + event.code;
- }
- }
-
- let errorModal = new bootstrap.Modal(document.getElementById('error'));
- errorModal.show();
- modal.hide();
- }
-
- socket.onmessage = async (event) => {
- let data = JSON.parse(event.data);
- if (data.task !== "HEARTBEAT_ACK") console.log("[ws:message]", data);
-
- if (data.task === "CONFIG") {
- document.getElementById("invite-input-1").disabled = false;
- document.getElementById("invite-input-2").disabled = false;
- document.getElementById("invite-input-3").disabled = false;
- document.getElementById("invite-input-4").disabled = false;
- document.getElementById("invite-input-5").disabled = false;
- document.getElementById("invite-input-6").disabled = false;
- document.getElementById("invite-input-7").disabled = false;
- document.getElementById("invite-input-8").disabled = false;
- document.getElementById("host-start").classList.remove("disabled");
-
- setInterval(() => {
- socket.send(JSON.stringify({
- task: "HEARTBEAT",
- payload: {
- videoPositon: document.getElementById("video").currentTime
- }
- }));
- }, data.payload.heartbeatInterval);
-
- return;
- }
-
- if (data.task === "SESSION") {
- window.users = data.payload.users;
- window.queue = data.payload.queue;
-
- updateQueue();
-
- document.getElementById("participants").innerHTML = "";
- for (let user of data.payload.users) {
- document.getElementById("participants").innerHTML += "<li class='list-group-item'>" + user.id + "<span id='user-" + user.id + "-ping' class='bg-primary user-ping'></span></li>";
- }
-
- document.getElementById("invite-code").innerText = data.payload.code;
- }
-
- if (data.task === "VIDEO_UPDATE") {
- if (data.payload.id !== null) {
- try {
- window.segments = JSON.parse(await (await window.fetch("https://sponsor.ajay.app/api/skipSegments/" + data.payload.sha.substring(0, 32) + '?categories=["sponsor","intro","outro","music_offtopic"]')).text()).filter(i => i['videoID'] === data.payload.id)[0].segments;
- notification("This video is enhanced by smart playback", "success");
- } catch (e) {
- notification("This video is not compatible with smart playback", "warning");
- window.segments = [];
- }
- }
-
- if (data.payload.url) document.getElementById("video").src = data.payload.url;
-
- if (data.payload.state === 1) {
- document.getElementById("video").play();
- } else if (!!data.payload.state) {
- document.getElementById("video").pause();
- }
-
- if (data.payload.title && data.payload.title.trim() !== "") {
- document.getElementById("video-title").innerText = data.payload.title;
- document.title = data.payload.title + " · " + window.originalTitle;
- } else {
- if (data.payload.title) {
- document.getElementById("video-title").innerText = "";
- document.title = window.originalTitle;
- }
- }
-
- document.getElementById("video").currentTime = data.payload.position;
- }
-
- if (data.task === "UPDATE_USERS") {
- window.users = data.payload.users;
-
- document.getElementById("participants").innerHTML = "";
- for (let user of data.payload.users) {
- document.getElementById("participants").innerHTML += "<li class='list-group-item'>" + user.id + "<span id='user-" + user.id + "-ping' class='bg-primary user-ping'></span></li>";
- }
- }
-
- if (data.task === "UPDATE_QUEUE") {
- window.queue = data.payload.queue;
-
- if (data.payload.poster === identity.id) {
- document.getElementById("add-id").disabled = false;
- document.getElementById("add-id").value = "";
- document.getElementById("add-btn-yes").classList.remove("disabled");
- document.getElementById("add-btn-no").classList.remove("disabled");
-
- modalAdd.hide();
- }
-
- updateQueue();
- }
-
- if (data.task === "HEARTBEAT_ACK") {
- for (let user of Object.keys(data.payload.delays)) {
- let abs = Math.abs(data.payload.delays[user]);
- let color = "primary";
-
- if (abs >= 500) color = "warning";
- if (abs >= 1000) color = "danger";
- if (abs < 500) color = "success";
-
- let sign = "±";
- if (data.payload.delays[user] < 0) sign = "-";
- if (data.payload.delays[user] > 0) sign = "+";
-
- document.getElementById("user-" + user + "-ping").title = sign + abs + " ms";
- document.getElementById("user-" + user + "-ping").classList.remove("bg-primary");
- document.getElementById("user-" + user + "-ping").classList.remove("bg-danger");
- document.getElementById("user-" + user + "-ping").classList.remove("bg-warning");
- document.getElementById("user-" + user + "-ping").classList.remove("bg-green");
- document.getElementById("user-" + user + "-ping").classList.add("bg-" + color);
- }
- }
-
- if (data.task === "TERMINATE" || data.task === "FAILURE") {
- window.terminated = true;
-
- if (data.payload.code) {
- if (data.payload.reason) {
- document.getElementById('error-message').innerText = data.payload.code + ": " + data.payload.reason;
- let errorModal = new bootstrap.Modal(document.getElementById('error'));
- errorModal.show();
- } else {
- document.getElementById('error-message').innerText = data.payload.code;
- let errorModal = new bootstrap.Modal(document.getElementById('error'));
- errorModal.show();
- }
- } else {
- document.getElementById('error-message').innerText = "Error";
- let errorModal = new bootstrap.Modal(document.getElementById('error'));
- errorModal.show();
- }
-
- if (data.task === "FAILURE") socket.close();
- }
- }
-
- socket.onopen = (event) => {
- console.log("[ws:open] ", event);
-
- socket.send(JSON.stringify({
- task: "IDENTIFY",
- payload: {
- token: window.sessionToken
- }
- }))
- }
- }
-
- function updateQueue() {
- document.getElementById("queue").innerHTML = "";
-
- for (let video of window.queue) {
- document.getElementById("queue").innerHTML += `
-<li class="list-group-item list-group-item-action video-queue-item">
- <div class="video-queue-item-part video-queue-item-metadata">
- <div>
- <div class="video-queue-item-title-outer">
- <span class="video-queue-item-title">${video.title}</span>
- </div>
- <div class="video-queue-item-author-outer">
- <span class="video-queue-item-author text-muted">${video.author}</span>
- </div>
- </div>
- </div>
- <div class="video-queue-item-part text-muted">${video['duration_pretty'] ?? toPrettyTime(video.duration)}</div>
-</li>
-`;
- }
- }
-
- function startSession() {
- socket.send(JSON.stringify({
- task: "SESSION",
- payload: {
- id: window.inviteCode
- }
- }))
-
- modal.hide();
- }
-
- connect();
-</script>
-
-<div style="height:calc(100vh - 60px);display:grid;grid-template-columns: 3fr 1.5fr;" id="app-container">
- <div style="height:calc(100vh - 60px);">
- <video id="video" style="width:100%;height:calc(100vh - 60px);"></video>
- </div>
- <script>
-
- document.getElementById("video").onplay = () => {
- console.log("play");
-
- if (socket) socket.send(JSON.stringify({
- task: "VIDEO_UPDATE",
- payload: {
- state: 1,
- position: document.getElementById("video").currentTime
- }
- }));
- }
-
- document.getElementById("video").onpause = () => {
- console.log("pause");
-
- if (socket) socket.send(JSON.stringify({
- task: "VIDEO_UPDATE",
- payload: {
- state: 0,
- position: document.getElementById("video").currentTime
- }
- }));
- }
-
- let controlsFadeInterval;
- document.body.classList.remove("hide-controls");
-
- document.body.onmousemove = document.body.onmouseup = () => {
- document.body.classList.remove("hide-controls");
- try { clearTimeout(controlsFadeInterval) } catch (e) {}
- controlsFadeInterval = setTimeout(() => {
- if (!document.getElementById("video").paused) document.body.classList.add("hide-controls");
- }, 5000);
- }
-
- </script>
- <div class="container" id="sidebar" style="border-left:1px solid rgba(255, 255, 255, .25);">
- <br>
- <h4>Participants</h4>
- <ul class="list-group" id="participants"></ul>
- <p style="margin-top:10px;margin-bottom:0;">Invite new participants with this invite code: <code id="invite-code">--------</code></p>
-
- <br>
- <h4>Queue</h4>
- <ul class="list-group" id="queue"></ul>
- <p style="margin-top:10px;margin-bottom:0;">
- <span class="btn btn-primary" onclick="openAdd()">Add video</span>
- </p>
- </div>
-</div>
-
-<div id="notification" style="z-index:999;padding: 15px 20px;font-size: 20px;position: fixed;top: 60px;left:0;text-shadow: 0 0 10px black;">
- Notification.
-</div>
-<a onclick="controls_skipIntroOutro();" id="skipper">Skip</a>
-<div id="controls-outer" style="position:fixed;background: linear-gradient(180deg, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0) 35%, rgba(0,0,0,0) 65%, rgba(0,0,0,0.5) 100%);top: 60px;left: 0;right: 0;bottom: 0;">
- <div id="video-title" style="padding: 15px 20px;font-size: 20px;"></div>
- <div id="controls" style="position: fixed;bottom: 20px;height: 50px;left: 15px;display:grid;grid-template-columns: max-content 1fr max-content;">
- <div>
- <a id="control-play" onclick="controls_playPause();" class="control-item">
- <img alt="" src="/assets/icons/together/play.svg" id="control-play-icon" class="control-icon">
- </a>
- <a id="control-next" onclick="controls_next();" class="control-item">
- <img alt="" src="/assets/icons/together/next.svg" id="control-next-icon" class="control-icon">
- </a>
- </div>
- <div style="display: flex;align-items: center;padding-left:15px;padding-right:15px;">
- <div style="padding: 22px 0;width:100%;" id="seek-bar">
- <div style="height:6px;width:100%;background:rgba(255, 255, 255, .1);border-radius:999px;pointer-events: none;">
- <div style="height:6px;width:0;background:rgba(255, 255, 255, .75);border-radius:999px;" id="control-progress"></div>
- </div>
- </div>
- </div>
- <div>
- <div style="display: inline-flex;align-items: center;">
- <span id="time-remaining" style="font-family:monospace;">-0:00</span>
- </div>
- <a id="control-full" onclick="controls_fullscreen();" class="control-item">
- <img alt="" src="/assets/icons/together/full-on.svg" id="control-full-icon" class="control-icon">
- </a>
- </div>
- </div>
- <div id="seek-bar-dot" style="position: fixed;bottom: 38px;width: 12px;height: 12px;background: white;border-radius: 999px;pointer-events: none;display:none;"></div>
-</div>
-<script>
- document.getElementById("controls").style.width = (document.getElementById("video").clientWidth - 30) + "px";
- document.getElementById("controls-outer").style.right = (window.innerWidth - document.getElementById("video").clientWidth) + "px";
- document.getElementById("notification").style.right = (window.innerWidth - document.getElementById("video").clientWidth) + "px";
-
- let notificationDecayTimeout;
-
- function notification(text, color) {
- document.getElementById("notification").innerText = text;
- document.getElementById("notification").classList.add("text-" + color);
- document.body.classList.add("notification");
-
- try { clearTimeout(notificationDecayTimeout) } catch (e) {}
-
- notificationDecayTimeout = setTimeout(() => {
- document.body.classList.remove("notification");
- setTimeout(() => {
- document.getElementById("notification").innerText = "Notification.";
- document.getElementById("notification").classList.remove("text-" + color);
- }, 200);
- }, 5000)
- }
-
- window.onresize = () => {
- document.getElementById("controls").style.width = (document.getElementById("video").clientWidth - 30) + "px";
- document.getElementById("controls-outer").style.right = (window.innerWidth - document.getElementById("video").clientWidth) + "px";
- document.getElementById("notification").style.right = (window.innerWidth - document.getElementById("video").clientWidth) + "px";
- }
-
- function controls_playPause() {
- if (document.getElementById("video").src.trim() === "") return;
-
- if (document.getElementById("video").paused) {
- document.getElementById("video").play();
- } else {
- document.getElementById("video").pause();
- }
- }
-
- function controls_fullscreen() {
- if (document.fullscreen) {
- document.exitFullscreen();
- } else {
- document.documentElement.requestFullscreen();
- }
- }
-
- function controls_next() {
- document.getElementById("video").play();
- document.getElementById("video").currentTime = document.getElementById("video").duration;
- }
-
- window.seeking = false;
- window.seekPosition = 0;
-
- document.getElementById("controls-outer").onclick = (event) => {
- if (event.target === document.getElementById("controls-outer")) controls_playPause();
- }
-
- document.getElementById("controls-outer").ondblclick = (event) => {
- if (event.target === document.getElementById("controls-outer")) controls_fullscreen();
- }
-
- document.getElementById("seek-bar").onmouseenter = () => {
- document.getElementById("seek-bar-dot").style.display = "";
- console.log("> ENTER <");
- window.seeking = true;
- }
-
- document.getElementById("seek-bar").onclick = (event) => {
- let percentage = (event.offsetX / document.getElementById("seek-bar").clientWidth) * 100;
- let multiplier = event.offsetX / document.getElementById("seek-bar").clientWidth;
-
- document.getElementById("seek-bar-dot").style.left = event.clientX + "px";
-
- console.log(" CLICK: ", event.offsetX, "(" + percentage.toFixed(3) + "%, " + toPrettyTime(document.getElementById("video").duration * multiplier) + ")");
- window.seekPosition = document.getElementById("video").duration * multiplier;
-
- document.getElementById("video").pause();
- document.getElementById("video").currentTime = window.seekPosition;
- document.getElementById("video").play();
- }
-
- document.getElementById("seek-bar").onmouseleave = () => {
- document.getElementById("seek-bar-dot").style.display = "none";
- console.log("< LEAVE >");
- window.seeking = false;
- }
-
- function controls_skipIntroOutro() {
- let skipper = null;
-
- for (let segment of window.segments.filter(i => i['category'] === "intro")) {
- if (segment.segment) {
- if (document.getElementById("video").currentTime >= segment.segment[0] && document.getElementById("video").currentTime < segment.segment[1]) {
- skipper = segment.segment[1];
- }
- }
- }
- for (let segment of window.segments.filter(i => i['category'] === "outro")) {
- if (segment.segment) {
- if (document.getElementById("video").currentTime >= segment.segment[0] && document.getElementById("video").currentTime < segment.segment[1]) {
- skipper = segment.segment[1];
- }
- }
- }
-
- if (skipper) {
- document.getElementById("video").pause();
- document.getElementById("video").currentTime = skipper;
- document.getElementById("video").play();
- }
- }
-
- document.getElementById("seek-bar").onmousemove = (event) => {
- let percentage = (event.offsetX / document.getElementById("seek-bar").clientWidth) * 100;
- let multiplier = event.offsetX / document.getElementById("seek-bar").clientWidth;
-
- document.getElementById("seek-bar-dot").style.left = event.clientX + "px";
-
- console.log(" POS: ", event.offsetX, "(" + percentage.toFixed(3) + "%, " + toPrettyTime(document.getElementById("video").duration * multiplier) + ")");
- window.seekPosition = document.getElementById("video").duration * multiplier;
- }
-
- setInterval(() => {
- if (document.getElementById("video").src.trim() === "") {
- document.getElementById("controls").style.display = "none";
- } else {
- document.getElementById("controls").style.display = "grid";
- }
-
- document.getElementById("control-play-icon").src = document.getElementById("video").paused ? "/assets/icons/together/play.svg" : "/assets/icons/together/pause.svg";
- document.getElementById("control-full-icon").src = document.fullscreen ? "/assets/icons/together/full-off.svg" : "/assets/icons/together/full-on.svg";
- document.getElementById("control-progress").style.width = ((document.getElementById("video").currentTime / document.getElementById("video").duration) * 100) + "%";
-
- if (document.fullscreen) {
- document.body.classList.add("fullscreen");
- } else {
- document.body.classList.remove("fullscreen");
- }
-
- if (window.seeking) {
- document.getElementById("time-remaining").classList.add("text-warning");
- document.getElementById("time-remaining").innerText = toPrettyTime(window.seekPosition);
- } else {
- document.getElementById("time-remaining").classList.remove("text-warning");
-
- if (!isNaN(document.getElementById("video").duration)) {
- document.getElementById("time-remaining").innerText = "-" + toPrettyTime(Math.round(document.getElementById("video").duration) - Math.round(document.getElementById("video").currentTime));
- } else {
- document.getElementById("time-remaining").innerText = "-0:00";
- }
- }
- })
-
- setInterval(() => {
- if (!document.getElementById("video").paused) {
- for (let segment of window.segments.filter(i => i['category'] === "sponsor")) {
- if (segment.segment) {
- if (document.getElementById("video").currentTime >= segment.segment[0] && document.getElementById("video").currentTime < segment.segment[1]) {
- document.getElementById("video").pause();
- document.getElementById("video").currentTime = segment.segment[1];
- document.getElementById("video").play();
- notification("Advert skipped by smart playback", "primary");
- }
- }
- }
-
- let skipper = false;
-
- for (let segment of window.segments.filter(i => i['category'] === "intro")) {
- if (segment.segment) {
- if (document.getElementById("video").currentTime >= segment.segment[0] && document.getElementById("video").currentTime < segment.segment[1]) {
- skipper = true;
- document.getElementById("skipper").innerText = "Skip intro";
- document.body.classList.add("skipper");
- }
- }
- }
- for (let segment of window.segments.filter(i => i['category'] === "outro")) {
- if (segment.segment) {
- if (document.getElementById("video").currentTime >= segment.segment[0] && document.getElementById("video").currentTime < segment.segment[1]) {
- skipper = true;
- document.getElementById("skipper").innerText = "Skip to the end";
- document.body.classList.add("skipper");
- }
- }
- }
-
- if (!skipper) {
- document.body.classList.remove("skipper");
- }
- }
- })
-</script> \ No newline at end of file