// ==UserScript== // @name Copy token from skland for ark.yituliu.cn // @name:zh-CN 一键复制明日方舟一图流所需的森空岛token // @namespace ling921 // @version 0.2.0 // @description Script to copy skland token to ark.yituliu.cn // @description:zh-CN 脚本用于复制森空岛token到明日方舟一图流中使用,并支持Shift+C快捷键 // @author ling921 // @match https://www.skland.com/* // @icon https://ark.yituliu.cn/favicon.ico // @grant none // @run-at document-idle // @tag utilities // @tag game // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/520836/Copy%20token%20from%20skland%20for%20arkyituliucn.user.js // @updateURL https://update.greasyfork.icu/scripts/520836/Copy%20token%20from%20skland%20for%20arkyituliucn.meta.js // ==/UserScript== /** * 通知管理器类 */ class NotificationManager { static #instance = null; static #maxNotifications = 3; static #defaultDuration = 3000; static #queue = []; static #active = new Set(); static #container = null; /** * 获取通知管理器实例 * @param {{ * maxNotifications?: number, * duration?: number * }} options - 配置选项 */ static getInstance(options = {}) { if (!NotificationManager.#instance) { if (options.maxNotifications && options.maxNotifications > 0) { NotificationManager.#maxNotifications = options.maxNotifications; } if (options.duration && options.duration > 0) { NotificationManager.#defaultDuration = options.duration; } NotificationManager.#instance = new NotificationManager(options); } return NotificationManager.#instance; } constructor() { if (NotificationManager.#instance) { return NotificationManager.#instance; } NotificationManager.#container = document.getElementById( "notification-container" ); if (!NotificationManager.#container) { const style = document.createElement("style"); style.textContent = ` #notification-container { position: fixed; top: 20px; left: 0; right: 0; display: flex; flex-direction: column; align-items: center; gap: 12px; pointer-events: none; z-index: 10000; } #notification-container .notification { position: relative; padding: 10px 25px; padding-right: 35px !important; border-radius: 20px; font-size: 14px; color: white; font-family: "PingFang SC", "Microsoft YaHei", sans-serif; opacity: 0; transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); text-align: center; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); transform: translateY(-20px); pointer-events: auto; } #notification-container .notification:hover { filter: brightness(1.1); } #notification-container .notification .close { position: absolute !important; right: 10px !important; top: 50% !important; transform: translateY(-50%) !important; width: 16px !important; height: 16px !important; cursor: pointer !important; opacity: 0.7 !important; transition: opacity 0.2s !important; display: flex !important; align-items: center !important; justify-content: center !important; user-select: none !important; } #notification-container .notification .close:hover { opacity: 1 !important; } #notification-container .success { background-color: #52c41a !important; box-shadow: 0 4px 12px rgba(82, 196, 26, 0.3) !important; border-color: rgba(255, 255, 255, 0.2) !important; } #notification-container .info { background-color: #1890ff !important; box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3) !important; border-color: rgba(255, 255, 255, 0.15) !important; } #notification-container .warning { background-color: #faad14 !important; box-shadow: 0 4px 12px rgba(250, 173, 20, 0.3) !important; border-color: rgba(255, 255, 255, 0.1) !important; } #notification-container .error { background-color: #ff4d4f !important; box-shadow: 0 4px 12px rgba(255, 77, 79, 0.3) !important; border-color: rgba(255, 255, 255, 0.1) !important; } `; document.head.appendChild(style); NotificationManager.#container = document.createElement("div"); NotificationManager.#container.id = "notification-container"; document.body.appendChild(NotificationManager.#container); } NotificationManager.#instance = this; } success(message, duration) { this.#show(message, "success", duration); } info(message, duration) { this.#show(message, "info", duration); } warning(message, duration) { this.#show(message, "warning", duration); } error(message, duration) { this.#show(message, "error", duration); } #show(message, type, duration) { if (!duration || duration <= 0) { duration = NotificationManager.#defaultDuration; } NotificationManager.#queue.push({ message, type, duration }); NotificationManager.#processQueue(); } static #processQueue() { if ( NotificationManager.#queue.length === 0 || NotificationManager.#active.size >= NotificationManager.#maxNotifications ) { return; } const { message, type, duration } = NotificationManager.#queue.shift(); NotificationManager.#showNotification(message, type, duration); if (NotificationManager.#queue.length > 0) { NotificationManager.#processQueue(); } } static #showNotification( message, type, duration = NotificationManager.#defaultDuration ) { const notify = document.createElement("div"); notify.classList.add("notification", type); const messageText = document.createElement("span"); messageText.textContent = message; notify.appendChild(messageText); const removeNotify = () => { notify.style.opacity = "0"; notify.style.transform = "translateY(-20px)"; setTimeout(() => { notify.remove(); NotificationManager.#active.delete(notify); NotificationManager.#processQueue(); }, 300); }; const closeBtn = document.createElement("div"); closeBtn.classList.add("close"); closeBtn.innerHTML = "✕"; closeBtn.onclick = removeNotify; notify.appendChild(closeBtn); let timer; notify.addEventListener("mouseenter", () => { clearTimeout(timer); }); notify.addEventListener("mouseleave", () => { timer = setTimeout(removeNotify, duration); }); NotificationManager.#container.appendChild(notify); NotificationManager.#active.add(notify); requestAnimationFrame(() => { notify.style.opacity = "1"; notify.style.transform = "translateY(0)"; }); timer = setTimeout(removeNotify, duration); } } /** * 防抖复制令牌 */ const debouncedCopyToken = debounce(copyToken, 300); /** * 消息通知 */ const message = NotificationManager.getInstance(); (function () { ("use strict"); // 添加按钮 const button = createButton(); document.body.appendChild(button); // 添加快捷键 document.addEventListener("keydown", (event) => { if (event.shiftKey && event.key.toLowerCase() === "c") { event.preventDefault(); debouncedCopyToken(); } }); })(); /** * 创建按钮 * @returns {HTMLElement} - 按钮元素 */ function createButton() { // 创建按钮 const button = document.createElement("div", { class: "copy-button" }); button.innerHTML = `