141 lines
6.9 KiB
JavaScript
141 lines
6.9 KiB
JavaScript
import videojs from "video.js";
|
||
import TachVideoMenuButton from "./components/tach-video-menu-button";
|
||
import TachVideoMenuItem from "./components/tach-video-menu-item";
|
||
import audioTrackSelector from "./selectors/audio-track-selector";
|
||
import playbackRateSelector from "./selectors/playback-rate-selector";
|
||
import qualityRateSelector from "./selectors/quality-rate-selector";
|
||
import textTracksSelector from "./selectors/text-track-selector";
|
||
import "./settings.css";
|
||
const BasePlugin = videojs.getPlugin("plugin");
|
||
// Значения опций по умолчанию
|
||
const defaults = {};
|
||
class SettingsButton extends BasePlugin {
|
||
constructor(player, options) {
|
||
super(player);
|
||
this.mainMenu = [];
|
||
this.options = videojs.obj.merge(defaults, options);
|
||
this.player.ready(() => this.initialize());
|
||
}
|
||
/**
|
||
* Инициализация плагина: создание кнопки настроек и привязка событий
|
||
*/
|
||
initialize() {
|
||
this.createSettingsButton();
|
||
this.bindPlayerEvents();
|
||
}
|
||
/**
|
||
* Привязка событий плеера (например, для обновления меню)
|
||
*/
|
||
bindPlayerEvents() {
|
||
// При необходимости можно привязать событие, например:
|
||
// this.settingsButton.on("click", this.setMenu.bind(this, undefined, false, true));
|
||
}
|
||
/**
|
||
* Создание кнопки настроек и определение пунктов меню.
|
||
* Здесь создаются фабрики для формирования кнопок и устанавливается начальное меню.
|
||
*/
|
||
createSettingsButton() {
|
||
const player = this.player;
|
||
// Создаем кнопку настроек с помощью компонента TachVideoMenuButton
|
||
this.settingsButton = new TachVideoMenuButton(player, "Settings", "Settings");
|
||
this.buttonInstance = player.controlBar.addChild(this.settingsButton, {
|
||
componentClass: "settingsButton",
|
||
});
|
||
this.buttonInstance.addClass("vjs-settings-button");
|
||
// Определяем кнопку "Назад" для возврата в главное меню
|
||
this.backButton = {
|
||
label: "Назад",
|
||
value: this.mainMenu,
|
||
selectable: false,
|
||
selected: false,
|
||
onClick: () => this.setMenu(undefined, true, true),
|
||
className: "settings-back",
|
||
};
|
||
// Создаем фабрики для дополнительных настроек
|
||
const { menuItem: audioMenuItem, menuItems: audioMenuItems } = audioTrackSelector(player);
|
||
this.audioTracksButton = () => ({
|
||
...audioMenuItem(),
|
||
onClick: () => this.setMenu(audioMenuItems(), false, true),
|
||
});
|
||
const { menuItem: textMenuItem, menuItems: textMenuItems } = textTracksSelector(player);
|
||
this.textTracksButton = () => ({
|
||
...textMenuItem(),
|
||
onClick: () => this.setMenu(textMenuItems(), false, true),
|
||
});
|
||
const { menuItem: playbackMenuItem, menuItems: playbackMenuItems } = playbackRateSelector(player);
|
||
this.playbackRateButton = () => ({
|
||
...playbackMenuItem(),
|
||
onClick: () => this.setMenu(playbackMenuItems(), false, true),
|
||
});
|
||
// В createSettingsButton замени этот участок:
|
||
const qualitySelector = qualityRateSelector(player);
|
||
this.qualityRateButton = () => ({
|
||
...qualitySelector.menuItem(), // пересоздание при каждом открытии меню
|
||
onClick: () => this.setMenu(qualitySelector.menuItems(), false, true),
|
||
});
|
||
// Подписка на автообновление, когда hls переключает уровень
|
||
qualitySelector.setMenuUpdateCallback(() => {
|
||
this.setMenu(undefined, true); // Обновить главное меню без перезахода
|
||
});
|
||
// Инициализируем меню с кнопками по умолчанию без показа
|
||
this.setMenu(undefined, true, false);
|
||
}
|
||
/**
|
||
* Обёртка для создания экземпляра пункта меню.
|
||
*
|
||
* @param item - объект настроек пункта меню
|
||
* @returns экземпляр TachVideoMenuItem
|
||
*/
|
||
getMenuItem(item) {
|
||
return new TachVideoMenuItem(this.player, item, this.settingsButton, this);
|
||
}
|
||
/**
|
||
* Устанавливает (обновляет) пункты меню плагина.
|
||
*
|
||
* @param items - массив пунктов меню (если не передан, используются кнопки по умолчанию)
|
||
* @param skipBackButton - если true, не добавлять кнопку "Назад"
|
||
* @param forceShow - если true, принудительно показать меню после обновления
|
||
*/
|
||
async setMenu(items = [], skipBackButton = false, forceShow = false) {
|
||
const menuButtons = [];
|
||
if (!skipBackButton) {
|
||
menuButtons.push(this.backButton);
|
||
}
|
||
if (items?.length === 0) {
|
||
// Если не переданы конкретные пункты меню – используем кнопки по умолчанию
|
||
const defaultButtons = [
|
||
this.playbackRateButton,
|
||
this.qualityRateButton,
|
||
this.textTracksButton,
|
||
this.audioTracksButton,
|
||
];
|
||
defaultButtons.forEach(createButton => {
|
||
const btn = createButton();
|
||
if (btn.enabled) {
|
||
menuButtons.push(btn);
|
||
}
|
||
});
|
||
}
|
||
else {
|
||
menuButtons.push(...items);
|
||
}
|
||
// Формируем список пунктов меню: вместо пересоздания меню, назначаем функцию,
|
||
// возвращающую актуальный список пунктов, и вызываем метод обновления.
|
||
this.settingsButton.createItems = () => menuButtons.map(item => this.getMenuItem(item));
|
||
await this.settingsButton.update();
|
||
// Если требуется принудительно показать меню, эмулируем клик по кнопке меню
|
||
if (forceShow) {
|
||
const menuElement = this.buttonInstance.el().querySelector(".vjs-menu");
|
||
const menuButton = this.buttonInstance
|
||
.el()
|
||
.querySelector(".vjs-menu-button");
|
||
if (menuElement && menuButton) {
|
||
menuButton.click();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// Регистрируем плагин в Video.js
|
||
videojs.registerPlugin("settingsMenu", SettingsButton);
|
||
export default SettingsButton;
|
||
//# sourceMappingURL=index.js.map
|