您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Right-click image upload to Mobilism - preserves native context menu
// ==UserScript== // @name Imgilism - Image Uploader (Improved) // @namespace http://tampermonkey.net/ // @version 1.1.0 // @description Right-click image upload to Mobilism - preserves native context menu // @author Sage & AI Improvements // @match http://*/* // @match https://*/* // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @grant GM_notification // @grant GM_setClipboard // @run-at document-start // ==/UserScript== (function() { 'use strict'; let imgilismMenu = null; let currentImageUrl = null; let menuTimeout = null; // Create styles for our menu addon const style = document.createElement('style'); style.textContent = ` .imgilism-addon-menu { position: fixed; background: #2c3e50; color: white; border: 2px solid #3498db; border-radius: 6px; box-shadow: 0 4px 15px rgba(0,0,0,0.3); z-index: 999999; min-width: 180px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; font-size: 13px; opacity: 0; transform: scale(0.95); transition: all 0.15s ease-out; } .imgilism-addon-menu.show { opacity: 1; transform: scale(1); } .imgilism-menu-header { padding: 8px 12px; background: #3498db; font-weight: bold; border-radius: 4px 4px 0 0; font-size: 12px; text-align: center; } .imgilism-menu-item { padding: 10px 15px; cursor: pointer; border-bottom: 1px solid #34495e; transition: all 0.2s; display: flex; align-items: center; } .imgilism-menu-item:hover { background: #3498db; padding-left: 20px; } .imgilism-menu-item:last-child { border-bottom: none; border-radius: 0 0 4px 4px; } .imgilism-menu-item .size-info { font-size: 11px; opacity: 0.7; margin-left: auto; } .imgilism-progress { padding: 12px 15px; background: #27ae60; color: white; font-style: italic; text-align: center; border-radius: 4px; } .imgilism-error { padding: 12px 15px; background: #e74c3c; color: white; text-align: center; border-radius: 4px; } .imgilism-close-btn { position: absolute; top: 2px; right: 5px; background: none; border: none; color: white; cursor: pointer; font-size: 16px; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; } `; document.head.appendChild(style); // Create our addon menu function createAddonMenu() { imgilismMenu = document.createElement('div'); imgilismMenu.className = 'imgilism-addon-menu'; imgilismMenu.innerHTML = ` <button class="imgilism-close-btn" title="Close">×</button> <div class="imgilism-menu-header">📸 Imgilism Upload</div> <div class="imgilism-menu-item" data-action="single"> Single <span class="size-info">320x240</span> </div> <div class="imgilism-menu-item" data-action="multiple"> Multiple <span class="size-info">240x160</span> </div> <div class="imgilism-menu-item" data-action="large"> Large <span class="size-info">500xAuto</span> </div> `; document.body.appendChild(imgilismMenu); // Add click handlers imgilismMenu.addEventListener('click', function(e) { if (e.target.classList.contains('imgilism-close-btn')) { hideAddonMenu(); return; } const action = e.target.closest('.imgilism-menu-item')?.dataset.action; if (action && currentImageUrl) { uploadImage(currentImageUrl, action); } }); } // Show addon menu near the mouse cursor function showAddonMenu(x, y, imageUrl) { currentImageUrl = imageUrl; if (!imgilismMenu) { createAddonMenu(); } // Position menu, ensuring it stays on screen const menuWidth = 180; const menuHeight = 140; let left = x + 10; // Offset from cursor let top = y - 10; // Keep menu on screen if (left + menuWidth > window.innerWidth) { left = x - menuWidth - 10; } if (top + menuHeight > window.innerHeight) { top = y - menuHeight + 10; } imgilismMenu.style.left = left + 'px'; imgilismMenu.style.top = top + 'px'; imgilismMenu.style.display = 'block'; // Smooth show animation setTimeout(() => imgilismMenu.classList.add('show'), 10); // Auto-hide after 10 seconds if not used clearTimeout(menuTimeout); menuTimeout = setTimeout(hideAddonMenu, 10000); } // Hide addon menu function hideAddonMenu() { if (imgilismMenu) { imgilismMenu.classList.remove('show'); setTimeout(() => { if (imgilismMenu) imgilismMenu.style.display = 'none'; }, 150); } currentImageUrl = null; clearTimeout(menuTimeout); } // Listen for right-clicks on images document.addEventListener('contextmenu', function(e) { const img = e.target.closest('img'); if (img && img.src) { // Small delay to let native menu appear first setTimeout(() => { showAddonMenu(e.clientX, e.clientY, img.src); }, 100); } else { hideAddonMenu(); } }); // Hide menu when clicking elsewhere or scrolling document.addEventListener('click', hideAddonMenu); document.addEventListener('scroll', hideAddonMenu); // Upload image function (keeping original logic) function uploadImage(imageUrl, sizeOption) { console.log('Starting image upload for:', imageUrl, 'with size option:', sizeOption); // Show progress if (imgilismMenu) { imgilismMenu.innerHTML = '<div class="imgilism-progress">🔄 Uploading image...</div>'; } // Configure size options let height, width, responseId; switch(sizeOption) { case 'single': height = '320'; width = ''; responseId = 'codehtml'; break; case 'multiple': height = '240'; width = '160'; responseId = 'codelbb'; break; case 'large': height = '500'; width = ''; responseId = 'codehtml'; break; } // Fetch the image GM_xmlhttpRequest({ method: 'GET', url: imageUrl, responseType: 'blob', timeout: 30000, onload: function(response) { if (response.status === 200) { const blob = response.response; const fileName = imageUrl.split(/[?#]/)[0].split('/').pop() || 'image.jpg'; const file = new File([blob], fileName, { type: blob.type }); // Create FormData const formData = new FormData(); formData.append('links', ''); formData.append('imgUrl', ''); formData.append('fileName[]', fileName); formData.append('Search files', 'Browse'); formData.append('file[]', file); formData.append('alt[]', fileName.replace(/[-_]/g, ' ').replace(/\.[^.]*$/, '')); formData.append('private[0]', '1'); formData.append('new_height[]', height); formData.append('new_width[]', width); formData.append('submit', 'Upload'); // Upload to Mobilism GM_xmlhttpRequest({ method: 'POST', url: 'https://images.mobilism.org/upload.php', data: formData, timeout: 60000, onload: function(uploadResponse) { if (uploadResponse.status === 200) { try { const parser = new DOMParser(); const responseDoc = parser.parseFromString(uploadResponse.responseText, 'text/html'); const urlElement = responseDoc.getElementById(responseId); if (urlElement && urlElement.value) { const uploadedUrl = urlElement.value.trim(); GM_setClipboard(uploadedUrl); // Show success if (imgilismMenu) { imgilismMenu.innerHTML = `<div class="imgilism-progress">✅ Copied to clipboard!<br><small>${uploadedUrl}</small></div>`; setTimeout(hideAddonMenu, 3000); } GM_notification({ text: 'Image uploaded! URL copied to clipboard.', title: 'Imgilism Success' }); } else { throw new Error('Upload URL not found in response'); } } catch (e) { console.error('Upload processing error:', e); showError('Failed to process upload response'); } } else { showError('Upload failed: ' + uploadResponse.statusText); } }, onerror: function() { showError('Upload request failed'); }, ontimeout: function() { showError('Upload timed out'); } }); } else { showError('Failed to fetch image: ' + response.statusText); } }, onerror: function() { showError('Failed to fetch image'); }, ontimeout: function() { showError('Image fetch timed out'); } }); } function showError(message) { console.error('Imgilism error:', message); if (imgilismMenu) { imgilismMenu.innerHTML = `<div class="imgilism-error">❌ ${message}</div>`; setTimeout(hideAddonMenu, 4000); } GM_notification({ text: message, title: 'Imgilism Error' }); } })();