Greasy Fork is available in English.
Adds a floating share button that appears when videos are detected. Hold down to copy instead of share.
当前为
// ==UserScript==
// @name Universal Video Share Button
// @namespace http://tampermonkey.net/
// @version 3.1
// @description Adds a floating share button that appears when videos are detected. Hold down to copy instead of share.
// @author Minoa
// @match *://*/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
var floatingButton = null;
var pressTimer = null;
var isLongPress = false;
var checkInterval = null;
// Common video selectors across different sites
var VIDEO_SELECTORS = [
'video',
'.video-player video',
'.player video',
'#player video',
'.video-container video',
'[class*="video"] video',
'[class*="player"] video',
'iframe[src*="youtube.com"]',
'iframe[src*="vimeo.com"]',
'iframe[src*="dailymotion.com"]',
'iframe[src*="twitch.tv"]',
'iframe[src*="pornhub.com"]',
'iframe[src*="xvideos.com"]'
];
// Function to get video URL from various sources
function getVideoUrl(videoElement) {
if (videoElement.tagName === 'VIDEO') {
if (videoElement.currentSrc) {
return videoElement.currentSrc;
}
if (videoElement.src) {
return videoElement.src;
}
var sources = videoElement.querySelectorAll('source');
for (var i = 0; i < sources.length; i++) {
if (sources[i].src) {
return sources[i].src;
}
}
}
if (videoElement.tagName === 'IFRAME') {
return videoElement.src;
}
return window.location.href;
}
// Function to get unique videos
function getUniqueVideos() {
var videos = [];
var seenUrls = [];
for (var s = 0; s < VIDEO_SELECTORS.length; s++) {
var selector = VIDEO_SELECTORS[s];
var elements = document.querySelectorAll(selector);
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
var rect = element.getBoundingClientRect();
if (rect.width > 100 && rect.height > 100) {
var url = getVideoUrl(element);
var isNewUrl = true;
for (var j = 0; j < seenUrls.length; j++) {
if (seenUrls[j] === url) {
isNewUrl = false;
break;
}
}
if (isNewUrl) {
seenUrls.push(url);
videos.push({
element: element,
url: url,
title: element.title || element.alt || ('Video ' + (videos.length + 1))
});
}
}
}
}
return videos;
}
// Function to create floating share button
function createFloatingButton() {
if (floatingButton) {
return floatingButton;
}
floatingButton = document.createElement('div');
floatingButton.innerHTML = '📤';
floatingButton.id = 'universal-video-share-float';
floatingButton.style.cssText = 'position: fixed; top: 20px; right: 20px; width: 50px; height: 50px; background: rgba(102, 126, 234, 0.9); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); color: white; border: 2px solid rgba(255, 255, 255, 0.2); border-radius: 50%; font-size: 18px; cursor: pointer; z-index: 999999; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; user-select: none; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);';
// Hover effects
floatingButton.addEventListener('mouseenter', function() {
this.style.transform = 'scale(1.1)';
this.style.background = 'rgba(102, 126, 234, 1)';
});
floatingButton.addEventListener('mouseleave', function() {
this.style.transform = 'scale(1)';
this.style.background = 'rgba(102, 126, 234, 0.9)';
});
// Handle mouse events for long press detection
floatingButton.addEventListener('mousedown', function(e) {
e.preventDefault();
isLongPress = false;
pressTimer = setTimeout(function() {
isLongPress = true;
floatingButton.style.background = 'rgba(46, 204, 113, 0.9)';
floatingButton.innerHTML = '📋';
}, 500);
});
floatingButton.addEventListener('mouseup', function(e) {
e.preventDefault();
clearTimeout(pressTimer);
floatingButton.style.background = 'rgba(102, 126, 234, 0.9)';
floatingButton.innerHTML = '📤';
if (isLongPress) {
handleCopy();
} else {
handleShare();
}
});
floatingButton.addEventListener('mouseleave', function() {
clearTimeout(pressTimer);
floatingButton.style.background = 'rgba(102, 126, 234, 0.9)';
floatingButton.innerHTML = '📤';
});
// Touch events for mobile
floatingButton.addEventListener('touchstart', function(e) {
e.preventDefault();
isLongPress = false;
pressTimer = setTimeout(function() {
isLongPress = true;
floatingButton.style.background = 'rgba(46, 204, 113, 0.9)';
floatingButton.innerHTML = '📋';
}, 500);
});
floatingButton.addEventListener('touchend', function(e) {
e.preventDefault();
clearTimeout(pressTimer);
floatingButton.style.background = 'rgba(102, 126, 234, 0.9)';
floatingButton.innerHTML = '📤';
if (isLongPress) {
handleCopy();
} else {
handleShare();
}
});
document.body.appendChild(floatingButton);
return floatingButton;
}
// Function to handle share action
function handleShare() {
var videos = getUniqueVideos();
if (videos.length === 0) {
showNotification('No videos found!', 'error');
return;
}
if (videos.length === 1) {
shareVideo(videos[0]);
} else {
showVideoSelector(videos, 'share');
}
}
// Function to handle copy action
function handleCopy() {
var videos = getUniqueVideos();
if (videos.length === 0) {
showNotification('No videos found!', 'error');
return;
}
if (videos.length === 1) {
copyVideoUrl(videos[0]);
} else {
showVideoSelector(videos, 'copy');
}
}
// Function to create video selector popup
function showVideoSelector(videos, action) {
// Remove existing selector if any
var existingSelector = document.querySelector('#video-selector-popup');
if (existingSelector) {
existingSelector.remove();
}
var popup = document.createElement('div');
popup.id = 'video-selector-popup';
popup.style.cssText = 'position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.8); backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px); z-index: 9999999; display: flex; align-items: center; justify-content: center; padding: 20px; box-sizing: border-box;';
var container = document.createElement('div');
container.style.cssText = 'background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border-radius: 15px; padding: 30px; max-width: 80%; max-height: 80%; overflow-y: auto; position: relative; box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);';
// Close button
var closeButton = document.createElement('button');
closeButton.innerHTML = '✕';
closeButton.style.cssText = 'position: absolute; top: 15px; right: 15px; background: none; border: none; font-size: 20px; cursor: pointer; color: #666; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center;';
closeButton.addEventListener('click', function() {
popup.remove();
});
closeButton.addEventListener('mouseenter', function() {
this.style.background = 'rgba(0, 0, 0, 0.1)';
});
closeButton.addEventListener('mouseleave', function() {
this.style.background = 'none';
});
// Title
var title = document.createElement('h3');
title.textContent = 'Select Video to ' + (action.charAt(0).toUpperCase() + action.slice(1));
title.style.cssText = 'margin: 0 0 20px 0; color: #333; font-size: 18px; text-align: center;';
container.appendChild(closeButton);
container.appendChild(title);
// Video list
for (var i = 0; i < videos.length; i++) {
var videoData = videos[i];
var videoItem = document.createElement('div');
videoItem.style.cssText = 'margin-bottom: 20px; padding: 15px; border: 2px solid #ddd; border-radius: 10px; cursor: pointer; transition: all 0.3s ease; background: rgba(255, 255, 255, 0.7);';
// Create a closure to capture the current videoData
(function(currentVideoData) {
videoItem.addEventListener('mouseenter', function() {
this.style.borderColor = '#667eea';
this.style.background = 'rgba(102, 126, 234, 0.1)';
});
videoItem.addEventListener('mouseleave', function() {
this.style.borderColor = '#ddd';
this.style.background = 'rgba(255, 255, 255, 0.7)';
});
// Create preview video element
if (currentVideoData.element.tagName === 'VIDEO') {
var previewVideo = document.createElement('video');
previewVideo.src = currentVideoData.url;
previewVideo.style.cssText = 'width: 100%; max-width: 300px; height: auto; border-radius: 5px; margin-bottom: 10px;';
previewVideo.controls = false;
previewVideo.muted = true;
previewVideo.preload = 'metadata';
videoItem.appendChild(previewVideo);
} else {
// For iframes, show a placeholder
var placeholder = document.createElement('div');
placeholder.style.cssText = 'width: 100%; max-width: 300px; height: 150px; background: #f0f0f0; border-radius: 5px; margin-bottom: 10px; display: flex; align-items: center; justify-content: center; color: #666; font-size: 14px;';
placeholder.textContent = 'Embedded Video';
videoItem.appendChild(placeholder);
}
// Video info
var videoInfo = document.createElement('div');
videoInfo.innerHTML = '<strong>Video ' + (i + 1) + '</strong><br><small style="color: #666; word-break: break-all;">' + currentVideoData.url + '</small>';
videoItem.appendChild(videoInfo);
// Click handler
videoItem.addEventListener('click', function() {
popup.remove();
if (action === 'share') {
shareVideo(currentVideoData);
} else {
copyVideoUrl(currentVideoData);
}
});
})(videoData);
container.appendChild(videoItem);
}
popup.appendChild(container);
// Click outside to close
popup.addEventListener('click', function(e) {
if (e.target === popup) {
popup.remove();
}
});
document.body.appendChild(popup);
}
// Function to share video
function shareVideo(videoData) {
var pageTitle = document.title;
if (navigator.share) {
navigator.share({
title: pageTitle,
url: videoData.url
}).then(function() {
showNotification('Video shared successfully!', 'success');
}).catch(function(error) {
console.log('Error sharing video:', error);
copyVideoUrl(videoData);
});
} else {
copyVideoUrl(videoData);
}
}
// Function to copy video URL
function copyVideoUrl(videoData) {
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(videoData.url).then(function() {
showNotification('Video URL copied to clipboard!', 'success');
}).catch(function() {
fallbackCopy(videoData.url);
});
} else {
fallbackCopy(videoData.url);
}
}
// Fallback copy method
function fallbackCopy(url) {
try {
var textArea = document.createElement('textarea');
textArea.value = url;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
if (document.execCommand('copy')) {
showNotification('Video URL copied to clipboard!', 'success');
} else {
showNotification('Could not copy URL', 'error');
}
document.body.removeChild(textArea);
} catch (err) {
showNotification('Copy failed', 'error');
}
}
// Function to show notification
function showNotification(message, type) {
if (type === undefined) {
type = 'success';
}
var existingNotifications = document.querySelectorAll('.universal-video-notification');
for (var i = 0; i < existingNotifications.length; i++) {
existingNotifications[i].remove();
}
var notification = document.createElement('div');
notification.textContent = message;
notification.className = 'universal-video-notification';
var bgColor = type === 'success' ? 'rgba(46, 204, 113, 0.95)' : 'rgba(231, 76, 60, 0.95)';
notification.style.cssText = 'position: fixed; top: 80px; right: 20px; background: ' + bgColor + '; backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); color: white; padding: 12px 20px; border-radius: 10px; z-index: 999998; font-weight: 600; font-size: 14px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); max-width: 300px; word-wrap: break-word; transform: translateX(100%); transition: transform 0.3s ease;';
document.body.appendChild(notification);
// Animate in
setTimeout(function() {
notification.style.transform = 'translateX(0)';
}, 100);
// Remove after 3 seconds
setTimeout(function() {
if (notification.parentNode) {
notification.style.transform = 'translateX(100%)';
setTimeout(function() {
notification.remove();
}, 300);
}
}, 3000);
}
// Function to check for videos and show/hide button
function checkForVideos() {
var videos = getUniqueVideos();
if (videos.length > 0) {
if (!floatingButton) {
createFloatingButton();
}
} else {
if (floatingButton) {
floatingButton.remove();
floatingButton = null;
}
}
}
// Initialize the script
function init() {
console.log('Universal Video Share Button script initialized');
// Check immediately
setTimeout(checkForVideos, 1000);
// Set up interval to check every 5 seconds
checkInterval = setInterval(checkForVideos, 5000);
}
// Start the script
init();
})();