您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a notepad functionality, specific to each chat
当前为
- // ==UserScript==
- // @name Xoul AI Notepad (Ready)
- // @namespace Xoul AI
- // @match https://xoul.ai/*
- // @grant none
- // @license MIT
- // @version 1.0
- // @description Adds a notepad functionality, specific to each chat
- // @icon https://i.imgur.com/REqi6Iw.png
- // @author LuxTallis
- // ==/UserScript==
- (function() {
- 'use strict';
- let currentChatKey = null;
- let currentNotepad = null;
- let buttonAdded = false; // Track if the button has been added
- // Create a style element and append it to the head to avoid CSP issues
- const style = document.createElement('style');
- style.textContent = `
- .notepad {
- position: fixed;
- top: 0;
- right: 0;
- width: 300px;
- height: calc(100vh - 10px);
- background-color: #0a0a0a;
- color: #ffffff;
- padding: 10px;
- box-shadow: 0 0 0px rgba(0, 0, 0, 0.5);
- transform: translateX(100%);
- transition: transform 0.3s ease-in-out;
- z-index: 10000;
- overflow-y: auto;
- }
- .toggle-button {
- position: relative;
- background-color: #4a4a4a;
- color: #ffffff;
- border: none;
- padding: 10px;
- cursor: pointer;
- }
- `;
- document.head.appendChild(style);
- // Function to get the current chat ID from the URL
- function getChatId() {
- const url = window.location.href;
- const chatId = url.match(/\/chats\/([a-f0-9\-]+)/);
- return chatId ? chatId[1] : null;
- }
- // Function to initialize or reinitialize the notepad
- function initializeNotepad() {
- const chatKey = getChatId();
- if (!chatKey || chatKey === currentChatKey) return; // Don't reinitialize if the chat ID is the same
- currentChatKey = chatKey;
- // If a notepad already exists, remove it
- if (currentNotepad) {
- currentNotepad.remove();
- }
- // Create the notepad container
- currentNotepad = document.createElement('div');
- currentNotepad.className = 'notepad';
- currentNotepad.contentEditable = true; // Make it editable
- // Load saved content from localStorage based on the chat ID
- const savedContent = localStorage.getItem(`notepadContent-${chatKey}`);
- currentNotepad.textContent = savedContent ? savedContent : 'Start typing...'; // Default text
- // Event listener to save content on each change
- currentNotepad.addEventListener('input', () => {
- localStorage.setItem(`notepadContent-${chatKey}`, currentNotepad.textContent);
- });
- // Add the notepad to the page
- document.body.appendChild(currentNotepad);
- }
- // Add the new button under a given element
- function addButtonUnder(targetElement) {
- // Check if the button already exists, to avoid duplicates
- if (!document.querySelector('#newButton')) {
- const button = document.createElement('button');
- button.id = 'newButton'; // Add an ID to easily reference and avoid duplicates
- button.textContent = '◙';
- button.style.cssText = 'margin: 10px 0; padding: 5px 10px; background-color: #28a74500; color: white; border: none; border-radius: 5px; cursor: pointer; display: block;';
- button.addEventListener('click', (e) => {
- e.stopPropagation(); // Prevent click from propagating to the document
- if (!currentNotepad) {
- initializeNotepad();
- }
- // Toggle the notepad visibility
- if (currentNotepad.style.transform === 'translateX(100%)') {
- currentNotepad.style.transform = 'translateX(0%)'; // Open the notepad
- } else {
- currentNotepad.style.transform = 'translateX(100%)'; // Close the notepad
- }
- });
- targetElement.insertAdjacentElement('afterend', button);
- }
- }
- // Wait for an element to load and execute the callback when it's found
- function waitForElement(selector, callback) {
- const observer = new MutationObserver(() => {
- const element = document.querySelector(selector);
- if (element) {
- observer.disconnect();
- callback(element);
- }
- });
- observer.observe(document.body, { childList: true, subtree: true });
- }
- // Main function to decide where to place the new button
- function placeButton() {
- const firstButton = document.querySelector('#customButton');
- if (firstButton) {
- // If the first button exists, place the new button below it
- addButtonUnder(firstButton);
- } else {
- // If the first button doesn't exist, place the new button under the fallback element
- waitForElement('a.Sidebar_link__0EvG_:nth-child(6)', addButtonUnder);
- }
- }
- // Use MutationObserver to recheck the DOM periodically
- const observer = new MutationObserver(placeButton);
- observer.observe(document.body, { childList: true, subtree: true });
- // Observer to detect URL changes and update the notepad accordingly
- const urlObserver = new MutationObserver(() => {
- const chatId = getChatId();
- if (chatId !== currentChatKey) {
- initializeNotepad();
- }
- });
- urlObserver.observe(document, { childList: true, subtree: true });
- // Close notepad when clicking outside of it
- function closeNotepadOnClickOutside(event) {
- if (currentNotepad && !currentNotepad.contains(event.target)) {
- currentNotepad.style.transform = 'translateX(100%)'; // Close the notepad
- }
- }
- // Attach the click event listener to the document to detect clicks outside
- document.addEventListener('click', closeNotepadOnClickOutside);
- // Initial call to place the button when the page is loaded
- placeButton();
- })();