150 lines
7.7 KiB
JavaScript
150 lines
7.7 KiB
JavaScript
import videojs from "video.js";
|
|
import "./skip-buttons.css";
|
|
const BACKWARD_SCROLL_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" style="width: 20%; max-width: 48px; height: auto;" fill="none"><path d="M41.1751 35.3188C40.5985 35.3188 40.1204 35.1359 39.5579 34.7984L25.2282 26.361C24.2298 25.7704 23.7938 25.0812 23.7938 24.2656C23.7938 23.4641 24.2298 22.775 25.2282 22.1844L39.5579 13.7469C40.1344 13.4094 40.5985 13.2266 41.1751 13.2266C42.2719 13.2266 43.2001 14.0703 43.2001 15.6312V32.9141C43.2001 34.475 42.2719 35.3188 41.1751 35.3188ZM21.8532 35.3188C21.2767 35.3188 20.7985 35.1359 20.236 34.7984L5.89231 26.361C4.90783 25.7704 4.47199 25.0812 4.47199 24.2656C4.47199 23.4641 4.90783 22.775 5.89231 22.1844L20.236 13.7469C20.7985 13.4094 21.2767 13.2266 21.8532 13.2266C22.9501 13.2266 23.8782 14.0703 23.8782 15.6312V32.9141C23.8782 34.475 22.9501 35.3188 21.8532 35.3188Z" fill="url(#paint0_linear_17944_473880)"/><defs><linearGradient id="paint0_linear_17944_473880" x1="43.2001" y1="23.9984" x2="4.80007" y2="23.9984" gradientUnits="userSpaceOnUse"><stop stop-color="white"/><stop offset="0.49" stop-color="white"/><stop offset="0.5" stop-color="white" stop-opacity="0.3"/><stop offset="1" stop-color="white" stop-opacity="0.3"/></linearGradient></defs></svg>`;
|
|
const FORWARD_SCROLL_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" style="width: 20%; max-width: 48px; height: auto;" fill="none"><path d="M2.82499 22.3188C3.40155 22.3188 3.87968 22.1359 4.44218 21.7984L18.7719 13.361C19.7703 12.7704 20.2063 12.0812 20.2063 11.2656C20.2063 10.4641 19.7703 9.775 18.7719 9.18437L4.44218 0.746875C3.86562 0.409375 3.40155 0.226562 2.82499 0.226562C1.72811 0.226562 0.799988 1.07031 0.799988 2.63125V19.9141C0.799988 21.475 1.72811 22.3188 2.82499 22.3188ZM22.1469 22.3188C22.7234 22.3188 23.2016 22.1359 23.764 21.7984L38.1077 13.361C39.0922 12.7704 39.5281 12.0812 39.5281 11.2656C39.5281 10.4641 39.0922 9.775 38.1077 9.18437L23.764 0.746875C23.2016 0.409375 22.7234 0.226562 22.1469 0.226562C21.05 0.226562 20.1219 1.07031 20.1219 2.63125V19.9141C20.1219 21.475 21.05 22.3188 22.1469 22.3188Z" fill="url(#paint0_linear_17959_7312)"/><defs><linearGradient id="paint0_linear_17959_7312" x1="0.799988" y1="10.9984" x2="39.2" y2="10.9984" gradientUnits="userSpaceOnUse"><stop stop-color="white"/><stop offset="0.49" stop-color="white"/><stop offset="0.5" stop-color="white" stop-opacity="0.3"/><stop offset="1" stop-color="white" stop-opacity="0.3"/></linearGradient></defs></svg>`;
|
|
const wakePlayerUI = (player) => {
|
|
const playerWithActivity = player;
|
|
playerWithActivity.reportUserActivity?.();
|
|
playerWithActivity.userActive?.(true);
|
|
player.el()?.focus?.();
|
|
};
|
|
const secondsLabel = (accumulated) => {
|
|
const seconds = Math.abs(accumulated);
|
|
const mod10 = seconds % 10;
|
|
const mod100 = seconds % 100;
|
|
if (mod10 === 1 && mod100 !== 11) {
|
|
return `${seconds} секунду`;
|
|
}
|
|
if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) {
|
|
return `${seconds} секунды`;
|
|
}
|
|
return `${seconds} секунд`;
|
|
};
|
|
const createSkipButton = (player, skip, direction) => {
|
|
const button = document.createElement("button");
|
|
button.type = "button";
|
|
button.className = `vjs-skip-button vjs-skip-button-${direction}`;
|
|
const icon = document.createElement("span");
|
|
icon.className = "icon-placeholder";
|
|
icon.textContent = String(skip);
|
|
button.appendChild(icon);
|
|
const scrollInfo = document.createElement("div");
|
|
scrollInfo.className = "scroll-info";
|
|
scrollInfo.style.display = "none";
|
|
const scrollIcon = document.createElement("span");
|
|
scrollIcon.className = `scroll-icon scroll-icon-${direction}`;
|
|
scrollIcon.innerHTML =
|
|
direction === "backward" ? BACKWARD_SCROLL_ICON : FORWARD_SCROLL_ICON;
|
|
scrollInfo.appendChild(scrollIcon);
|
|
const scrollText = document.createElement("span");
|
|
scrollText.className = "scroll-text";
|
|
scrollInfo.appendChild(scrollText);
|
|
button.appendChild(scrollInfo);
|
|
let accumulated = 0;
|
|
let timer = null;
|
|
const renderScrollInfo = () => {
|
|
if (accumulated === 0) {
|
|
scrollInfo.style.display = "none";
|
|
scrollText.textContent = "";
|
|
return;
|
|
}
|
|
scrollInfo.style.display = "flex";
|
|
scrollText.textContent = secondsLabel(accumulated);
|
|
};
|
|
button.addEventListener("click", () => {
|
|
wakePlayerUI(player);
|
|
accumulated += direction === "forward" ? skip : -skip;
|
|
renderScrollInfo();
|
|
if (timer) {
|
|
clearTimeout(timer);
|
|
}
|
|
timer = setTimeout(() => {
|
|
const currentTime = player.currentTime() || 0;
|
|
player.currentTime(currentTime + accumulated);
|
|
wakePlayerUI(player);
|
|
accumulated = 0;
|
|
renderScrollInfo();
|
|
}, 500);
|
|
});
|
|
return button;
|
|
};
|
|
class SkipButtonComponent extends videojs.getComponent("Component") {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.element = null;
|
|
}
|
|
createEl() {
|
|
const direction = this.options_.direction;
|
|
const skip = Number(this.options_.skip) || 10;
|
|
const el = super.createEl("div", {
|
|
className: `vjs-skip-button-component vjs-skip-${direction}`,
|
|
});
|
|
this.element = createSkipButton(this.player(), skip, direction);
|
|
el.appendChild(this.element);
|
|
return el;
|
|
}
|
|
}
|
|
class SkipBackwardButtonComponent extends SkipButtonComponent {
|
|
constructor(player, options) {
|
|
options.direction = "backward";
|
|
super(player, options);
|
|
}
|
|
}
|
|
class SkipForwardButtonComponent extends SkipButtonComponent {
|
|
constructor(player, options) {
|
|
options.direction = "forward";
|
|
super(player, options);
|
|
}
|
|
}
|
|
videojs.registerComponent("SkipBackwardButtonComponent", SkipBackwardButtonComponent);
|
|
videojs.registerComponent("SkipForwardButtonComponent", SkipForwardButtonComponent);
|
|
const skipButtonsPlugin = function (options) {
|
|
const player = this;
|
|
player.ready(() => {
|
|
player.addChild("SkipBackwardButtonComponent", { skip: options.skip });
|
|
player.addChild("SkipForwardButtonComponent", { skip: options.skip });
|
|
const triggerSkip = (direction) => {
|
|
const selector = `.vjs-skip-button-${direction}`;
|
|
const button = player.el().querySelector(selector);
|
|
wakePlayerUI(player);
|
|
button?.click();
|
|
};
|
|
const onKeydown = (event) => {
|
|
const active = document.activeElement;
|
|
const tag = active?.tagName;
|
|
const isEditable = tag === "INPUT" ||
|
|
tag === "TEXTAREA" ||
|
|
tag === "SELECT" ||
|
|
active?.getAttribute("contenteditable") === "true";
|
|
if (isEditable) {
|
|
return;
|
|
}
|
|
if (event.key === " " || event.code === "Space") {
|
|
event.preventDefault();
|
|
wakePlayerUI(player);
|
|
if (player.paused()) {
|
|
void player.play();
|
|
}
|
|
else {
|
|
player.pause();
|
|
}
|
|
return;
|
|
}
|
|
if (event.key === "ArrowRight") {
|
|
event.preventDefault();
|
|
triggerSkip("forward");
|
|
}
|
|
else if (event.key === "ArrowLeft") {
|
|
event.preventDefault();
|
|
triggerSkip("backward");
|
|
}
|
|
};
|
|
document.addEventListener("keydown", onKeydown);
|
|
player.on("dispose", () => {
|
|
document.removeEventListener("keydown", onKeydown);
|
|
});
|
|
});
|
|
};
|
|
videojs.registerPlugin("skipButtons", skipButtonsPlugin);
|
|
export default skipButtonsPlugin;
|
|
//# sourceMappingURL=skip-buttons.js.map
|