Bs ToastPopup

Popup for toast

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.sleazyfork.org/scripts/578336/1841909/Bs%20ToastPopup.js

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        Bsodergren Library
// @version     1.7.0
// @grant       GM_xmlhttpRequest
// @grant       nsafeWindow
// @license     MIT
// @namespace   https://greasyfork.org/users/984905
// ==/UserScript==

function showToast(message, duration = 3000, cmdElement = null) {
  // Create toast container if it doesn't exist
  let container = document.getElementById('tm-toast-container');
  if (!container) {
    container = document.createElement('div');
    container.id = 'tm-toast-container';
    container.style.position = 'fixed';
    container.style.top = '20px';
    container.style.left = '20px';
    container.style.zIndex = '999999';
    container.style.display = 'flex';
    container.style.flexDirection = 'column';
    container.style.gap = '10px';
    document.body.appendChild(container);
  }

  // Create toast element
  const toast = document.createElement('div');
  toast.textContent = message;
  toast.style.background = 'rgb(0, 0, 0)';
  toast.style.color = '#fff';
  toast.style.padding = '10px 16px';
  toast.style.borderRadius = '6px';
  toast.style.borderColor = 'white';
  toast.style.borderWidth = '3px';
  toast.style.borderStyle = 'double';
  toast.style.fontSize = '18px';
  toast.style.boxShadow = '0 2px 8px rgba(0,0,0,0.3)';
  toast.style.opacity = '0.5';
  toast.style.transition = 'opacity 0.3s ease';

  container.appendChild(toast);

  // Fade in
  requestAnimationFrame(() => {
    toast.style.opacity = '1';
  });

  // Remove after duration
  setTimeout(() => {
    toast.style.opacity = '0';
    toast.addEventListener('transitionend', () => {
      toast.remove();
      if (cmdElement !== null) {
        cmdElement();
      }
    });
  }, duration);
}

function waitForElement(selector, callback) {
  const observer = new MutationObserver(() => {
    const element = document.querySelector(selector);
    if (element) {
      observer.disconnect(); // Stop observing
      callback(element);
    }
  });

  // Observe changes in the entire document
  observer.observe(document.body, {
    childList: true,
    subtree: true,
  });
}

function jsonToUrlEncoded(jsonObj) {
  if (typeof jsonObj !== 'object' || jsonObj === null) {
    throw new Error('Input must be a non-null object');
  }
  return Object.keys(jsonObj)
    .map(
      key => encodeURIComponent(key) + '=' + encodeURIComponent(jsonObj[key])
    )
    .join('&');
}

function saveToLocalServer(postUrl, data, toast, command = null) {
  postUrl = 'http://media.lan/plex/' + postUrl;
  const encoded = jsonToUrlEncoded(data);

  GM_xmlhttpRequest({
    method: 'POST',
    url: postUrl,
    data: encoded,
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    responseType: 'document',
    onload: function (response) {
      var responseXML = response.responseXML;
      if (!responseXML) {
        try {
          responseXML = new DOMParser().parseFromString(
            response.responseText,
            'text/html'
          );
        } catch (err) { }
      }
      showToast(response.responseText, 3000, command);
    },
  });
}