您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Upload files to your Zipline instance with URL history, timestamps, minimize support, middle-click to open in new tab without shifting focus.
// ==UserScript== // @name My Zipline Uploader // @namespace *://*/* // @version 1.0 // @description Upload files to your Zipline instance with URL history, timestamps, minimize support, middle-click to open in new tab without shifting focus. // @author heapsofjoy // @match *://*/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // ==/UserScript== (function() { 'use strict'; // Create necessary DOM elements const uploadButton = document.createElement('div'); uploadButton.id = 'uploadButton'; uploadButton.innerHTML = '⬆'; document.body.appendChild(uploadButton); const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.style.display = 'none'; document.body.appendChild(fileInput); const urlTextBox = document.createElement('input'); urlTextBox.type = 'text'; urlTextBox.id = 'fileUrl'; urlTextBox.placeholder = 'URL will appear here'; urlTextBox.readOnly = true; urlTextBox.style.display = 'none'; document.body.appendChild(urlTextBox); const copyButton = document.createElement('div'); copyButton.id = 'copyButton'; copyButton.innerHTML = '📋'; copyButton.style.display = 'none'; document.body.appendChild(copyButton); const dropZone = document.createElement('div'); dropZone.id = 'dropZone'; dropZone.innerText = 'Drag & Drop File Here'; dropZone.style.display = 'none'; document.body.appendChild(dropZone); const minimizeButton = document.createElement('div'); minimizeButton.id = 'minimizeButton'; minimizeButton.innerHTML = '—'; minimizeButton.style.display = 'none'; document.body.appendChild(minimizeButton); const historyButton = document.createElement('div'); historyButton.id = 'historyButton'; historyButton.innerHTML = '📜'; historyButton.style.display = 'none'; document.body.appendChild(historyButton); const clearHistoryButton = document.createElement('div'); clearHistoryButton.id = 'clearHistoryButton'; clearHistoryButton.innerHTML = '🗑️'; clearHistoryButton.style.display = 'none'; document.body.appendChild(clearHistoryButton); const historyList = document.createElement('div'); historyList.id = 'historyList'; historyList.style.display = 'none'; document.body.appendChild(historyList); GM_addStyle(` #uploadButton, #historyButton, #clearHistoryButton, #minimizeButton { position: fixed; bottom: 0; width: 50px; height: 50px; background-color: #333; color: white; border: none; border-radius: 50%; cursor: pointer; font-family: Arial, sans-serif; font-size: 24px; text-align: center; line-height: 50px; box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2); z-index: 10000; } #uploadButton { left: 20px; transition: bottom 0.4s ease; } #uploadButton.minimized { bottom: 0; width: 50px; height: 10px; border-radius: 50px 50px 0 0; font-size: 10px; line-height: 10px; } #minimizeButton, #historyButton, #clearHistoryButton { width: 40px; height: 40px; font-size: 20px; line-height: 40px; } #minimizeButton { left: 80px; } #historyButton { left: 140px; } #clearHistoryButton { left: 200px; } #fileUrl, #historyList { position: fixed; bottom: 70px; left: 20px; width: 270px; background-color: #333; color: white; padding: 10px; border: none; border-radius: 5px; font-size: 14px; box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2); z-index: 10000; overflow-y: auto; } #fileUrl { display: block; } #historyList { height: 200px; display: none; } #historyList div { padding: 5px; border-bottom: 1px solid #555; cursor: pointer; color: #66ccff; } #historyList div span.timestamp { display: block; color: #aaa; font-size: 12px; margin-top: 2px; } #copyButton { position: fixed; bottom: 70px; left: 300px; width: 30px; height: 30px; background-color: #333; color: white; border: none; border-radius: 5px; cursor: pointer; font-family: Arial, sans-serif; font-size: 16px; text-align: center; line-height: 30px; box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2); z-index: 10000; } #dropZone { position: fixed; bottom: 120px; left: 20px; width: 300px; height: 150px; border: 2px dashed #aaa; background-color: #444; color: white; text-align: center; line-height: 150px; font-family: Arial, sans-serif; font-size: 14px; border-radius: 5px; z-index: 10000; } #dropZone.dragover { border-color: #fff; background-color: #555; } `); let isMinimized = true; uploadButton.classList.add('minimized'); uploadButton.addEventListener('click', () => { if (isMinimized) { uploadButton.classList.remove('minimized'); isMinimized = false; minimizeButton.style.display = 'block'; historyButton.style.display = 'block'; clearHistoryButton.style.display = 'block'; } else { fileInput.click(); } }); minimizeButton.addEventListener('click', () => { uploadButton.classList.add('minimized'); isMinimized = true; minimizeButton.style.display = 'none'; urlTextBox.style.display = 'none'; copyButton.style.display = 'none'; historyList.style.display = 'none'; historyButton.style.display = 'none'; clearHistoryButton.style.display = 'none'; dropZone.style.display = 'none'; }); fileInput.addEventListener('change', () => { const file = fileInput.files[0]; if (file) uploadFile(file); }); const uploadedUrlsKey = 'globalUploadedUrls'; const urlLimit = 10; // Limit the number of stored URLs // Load the saved URLs from GM storage let savedUrls = GM_getValue(uploadedUrlsKey, []); function updateHistoryList() { historyList.innerHTML = ''; const sortedUrls = [...savedUrls].reverse(); // Reverse order for recent-first sortedUrls.forEach(entry => { const urlElement = document.createElement('div'); urlElement.innerHTML = `${entry.url} <span class="timestamp">${entry.timestamp}</span>`; // Left-click to open in a new tab (focus) urlElement.addEventListener('click', () => { window.open(entry.url, '_blank'); }); // Middle-click to open in a background tab urlElement.addEventListener('auxclick', (e) => { if (e.button === 1) { window.open(entry.url, '_blank', 'noopener,noreferrer'); } }); historyList.appendChild(urlElement); }); } historyButton.addEventListener('click', () => { historyList.style.display = historyList.style.display === 'none' ? 'block' : 'none'; }); clearHistoryButton.addEventListener('click', () => { GM_setValue(uploadedUrlsKey, []); // Clear GM storage savedUrls = []; // Reset local array historyList.innerHTML = ''; // Clear the displayed list alert('History cleared!'); }); let dragCounter = 0; document.addEventListener('dragover', (e) => { e.preventDefault(); if (!isMinimized) { dragCounter++; dropZone.style.display = 'block'; dropZone.classList.add('dragover'); } }); document.addEventListener('dragleave', (e) => { e.preventDefault(); if (!isMinimized) { dragCounter--; if (dragCounter === 0) { dropZone.classList.remove('dragover'); dropZone.style.display = 'none'; } } }); dropZone.addEventListener('drop', (e) => { if (!isMinimized) { e.preventDefault(); dragCounter = 0; dropZone.classList.remove('dragover'); dropZone.style.display = 'none'; const file = e.dataTransfer.files[0]; if (file) uploadFile(file); } }); function uploadFile(file) { const formData = new FormData(); formData.append('file', file); // Use "file" as the form key per your ShareX config fetch('https://YOURZIPLINEINSTANCE.COM/api/upload', { method: 'POST', headers: { 'Authorization': 'TOKEN' // Replace with your actual token }, body: formData }) .then(response => response.json()) // Adjust to parse JSON response .then(data => { if (data && data.files && data.files[0]) { const url = data.files[0]; const timestamp = new Date().toLocaleString(); savedUrls.push({ url, timestamp }); // Check for limit and remove oldest if needed if (savedUrls.length > urlLimit) { savedUrls.shift(); // Remove the oldest entry } GM_setValue(uploadedUrlsKey, savedUrls); // Save to global storage urlTextBox.style.display = 'block'; urlTextBox.value = url; copyButton.style.display = 'block'; updateHistoryList(); } else { throw new Error('Invalid response format'); } }) .catch(error => { urlTextBox.value = 'Upload failed!'; console.error('Error:', error); }); } copyButton.addEventListener('click', () => { navigator.clipboard.writeText(urlTextBox.value).then(() => { copyButton.innerHTML = '✔'; setTimeout(() => copyButton.innerHTML = '📋', 1000); }).catch(error => console.error('Copy failed:', error)); }); updateHistoryList(); // Initial call to populate the history on load })();