您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
media panel in the catlife online
// ==UserScript== // @name media panel // @namespace http://tampermonkey.net/ // @version 2025-01-19 // @description media panel in the catlife online // @author me // @match https://worldcats.ru/play/ // @match https://worldcats.ru/play/?v=b // @match https://catlifeonline.com/play/ // @match https://catlifeonline.com/play/?v=b // @icon https://www.google.com/s2/favicons?sz=64&domain=catlifeonline.com // @grant none // ==/UserScript== (function() { // Проверяем, существует ли уже панель, чтобы избежать дублирования if (document.getElementById('media-viewer-panel')) { console.log('Панель просмотра медиа уже существует.'); return; } // --- 1. Создание структуры панели --- const panel = document.createElement('div'); panel.id = 'media-viewer-panel'; const header = document.createElement('div'); header.id = 'media-viewer-header'; header.innerHTML = 'Медиа-просмотрщик <span id="toggle-btn" style="cursor: pointer;">[ - ]</span>'; const contentArea = document.createElement('div'); contentArea.id = 'media-viewer-content'; contentArea.innerHTML = '<p style="text-align: center; color: #aaa;">Перетащите сюда видео, GIF или фото</p>'; panel.appendChild(header); panel.appendChild(contentArea); document.body.appendChild(panel); // --- 2. Стилизация и позиционирование (инлайн-стили для простоты в консоли) --- panel.style.cssText = ` position: fixed; bottom: 10px; left: 10px; width: 300px; /* Начальная ширина */ height: 300px; /* Начальная высота для видимости содержимого */ max-height: 80vh; /* Максимальная высота относительно окна просмотра */ min-height: 30px; /* Минимальная высота в свернутом виде (только заголовок) */ background-color: #222; border: 1px solid #444; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); z-index: 10000; display: flex; flex-direction: column; overflow: hidden; /* Скрыть контент при свертывании */ color: #eee; font-family: Arial, sans-serif; font-size: 14px; resize: both; /* Позволяет изменять размер панели */ min-width: 150px; max-width: 80vw; /* Максимальная ширина относительно окна просмотра */ transition: width 0.2s ease, height 0.2s ease; /* Плавное изменение размера */ `; header.style.cssText = ` background-color: #333; padding: 8px 12px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #444; user-select: none; /* Запрещает выделение текста в заголовке */ `; contentArea.style.cssText = ` flex-grow: 1; padding: 10px; overflow-y: auto; /* Прокрутка для содержимого */ display: flex; flex-direction: column; gap: 10px; /* Промежуток между элементами */ justify-content: flex-start; /* Элементы начинаются сверху */ align-items: center; /* Центрирование медиа по горизонтали */ min-width: 100px; /* Минимальная ширина контентной области */ min-height: 50px; /* Минимальная высота контентной области */ `; // --- 3. Функциональность свертывания/развертывания панели --- const toggleBtn = document.getElementById('toggle-btn'); let isCollapsed = false;toggleBtn.onclick = function() { if (isCollapsed) { contentArea.style.display = 'flex'; panel.style.height = '300px'; // Возвращаем к начальной высоте panel.style.maxHeight = '80vh'; // Возвращаем максимальную высоту toggleBtn.textContent = '[ - ]'; } else { contentArea.style.display = 'none'; panel.style.height = '30px'; // Сворачиваем до высоты заголовка panel.style.maxHeight = '30px'; // Ограничиваем максимальную высоту toggleBtn.textContent = '[ + ]'; } isCollapsed = !isCollapsed; }; // --- 4. Функциональность Drag and Drop --- contentArea.addEventListener('dragover', (e) => { e.preventDefault(); // Разрешаем drop contentArea.style.backgroundColor = 'rgba(68, 68, 68, 0.3)'; // Визуальная обратная связь }); contentArea.addEventListener('dragleave', (e) => { contentArea.style.backgroundColor = 'transparent'; // Убираем обратную связь }); contentArea.addEventListener('drop', (e) => { e.preventDefault(); contentArea.style.backgroundColor = 'transparent'; // Убираем обратную связь const files = e.dataTransfer.files; if (files.length > 0) { // Удаляем начальное сообщение "Перетащите сюда..." if (contentArea.querySelector('p')) { contentArea.innerHTML = ''; } for (let i = 0; i < files.length; i++) { const file = files[i]; // Проверяем тип файла: изображение или видео if (file.type.startsWith('image/') || file.type.startsWith('video/')) { // Создаем обертку для медиа и кнопки удаления const mediaWrapper = document.createElement('div'); mediaWrapper.style.cssText = ` position: relative; border: 1px solid #555; border-radius: 4px; overflow: hidden; margin-bottom: 5px; /* Отступ между элементами */ box-shadow: 0 2px 5px rgba(0,0,0,0.2); width: 100%; /* Обертка занимает всю доступную ширину */ display: flex; /* Для центрирования медиа внутри обертки */ justify-content: center; align-items: center; min-height: 50px; /* Минимальная высота для маленьких файлов */ `; let mediaElement; let objectURL; // Переменная для хранения URL, чтобы потом его отозвать if (file.type.startsWith('image/')) { mediaElement = document.createElement('img'); mediaElement.alt = file.name; objectURL = URL.createObjectURL(file); mediaElement.src = objectURL; } else if (file.type.startsWith('video/')) { mediaElement = document.createElement('video'); mediaElement.controls = true; // Добавляем элементы управления видео mediaElement.autoplay = false; // Не автовоспроизводить по умолчанию mediaElement.loop = true; // Зацикливать видео mediaElement.muted = true; // Отключаем звук по умолчанию objectURL = URL.createObjectURL(file); mediaElement.src = objectURL;// *** Обработка ошибок для видео *** mediaElement.onerror = function(e) { console.error(`Ошибка загрузки или воспроизведения медиа: ${file.name}.`, e); const errorDiv = document.createElement('div'); errorDiv.style.cssText = ` color: red; padding: 10px; text-align: center; background-color: #333; border-top: 1px solid #555; width: 100%; `; errorDiv.textContent = `Ошибка: Не удалось загрузить или воспроизвести "${file.name}"`; mediaWrapper.innerHTML = ''; // Очищаем обертку mediaWrapper.appendChild(errorDiv); mediaWrapper.appendChild(closeButton); // Важно: заново добавить кнопку закрытия // Отозвать URL, если ошибка произошла после его создания if (objectURL) { URL.revokeObjectURL(objectURL); objectURL = null; // Обнуляем, чтобы не пытаться отозвать дважды } }; } mediaElement.style.maxWidth = '100%'; // Масштабирование по ширине панели mediaElement.style.height = 'auto'; // Сохранение пропорций mediaElement.style.display = 'block'; mediaElement.style.borderRadius = '3px'; // Небольшое скругление углов медиа // Добавляем кнопку удаления const closeButton = document.createElement('span'); closeButton.classList.add('close-button'); // Добавляем класс для идентификации closeButton.innerHTML = '×'; // Символ "крестик" closeButton.style.cssText = ` position: absolute; top: 5px; right: 5px; background-color: rgba(0, 0, 0, 0.6); color: white; border-radius: 50%; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 16px; font-weight: bold; line-height: 1; /* Для лучшего выравнивания символа */ padding-bottom: 2px; transition: background-color 0.2s ease; z-index: 1; /* Убедимся, что кнопка поверх медиа */ `; closeButton.title = 'Удалить файл'; // Эффект при наведении closeButton.onmouseover = () => closeButton.style.backgroundColor = 'rgba(255, 0, 0, 0.7)'; closeButton.onmouseout = () => closeButton.style.backgroundColor = 'rgba(0, 0, 0, 0.6)'; closeButton.onclick = () => { mediaWrapper.remove(); // Удаляем всю обертку с медиа // Очень важно: отзываем URL, чтобы освободить память if (objectURL) { URL.revokeObjectURL(objectURL); console.log(`URL отозван: ${objectURL}`); } // Если больше нет медиа, показываем подсказку снова if (contentArea.children.length === 0) { contentArea.innerHTML = '<p style="text-align: center; color: #aaa;">Перетащите сюда видео, GIF или фото</p>'; } };mediaWrapper.appendChild(mediaElement); mediaWrapper.appendChild(closeButton); contentArea.appendChild(mediaWrapper); // Прокручиваем к низу, чтобы показать новый контент contentArea.scrollTop = contentArea.scrollHeight; } else { console.warn(`Медиа-просмотрщик: Неподдерживаемый тип файла: ${file.name} (${file.type})`); } } } }); console.log('Медиа-просмотрщик активирован. Панель в левом нижнем углу.'); console.log('Панель неперемещаема, но ее можно изменять по размеру, потянув за края.'); console.warn('Внимание: Запуск скриптов из консоли может быть небезопасным. Используйте этот скрипт только на надежных сайтах и понимая, что он делает.'); })();