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