Notepad For Character.ai

Adds a collapsable matte gray notepad on Character.AI chats, unique to each character page.

// ==UserScript==
// @name         Notepad For Character.ai
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Adds a collapsable matte gray notepad on Character.AI chats, unique to each character page.
// @author       Mr005K via ChatGPT
// @match        https://character.ai/*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // Create and style the notepad panel
    const notepadPanel = document.createElement('div');
    notepadPanel.style.position = 'fixed';
    notepadPanel.style.top = '0';
    notepadPanel.style.right = '0';
    notepadPanel.style.width = '300px';
    notepadPanel.style.height = '100%';
    notepadPanel.style.backgroundColor = '#4a4a4a';
    notepadPanel.style.color = '#ffffff';
    notepadPanel.style.padding = '10px';
    notepadPanel.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.5)';
    notepadPanel.style.transform = 'translateX(100%)';
    notepadPanel.style.transition = 'transform 0.3s ease-in-out';
    notepadPanel.style.zIndex = '1000';

    // Create the toggle button
    const toggleButton = document.createElement('button');
    toggleButton.textContent = '📝';
    toggleButton.style.position = 'fixed';
    toggleButton.style.top = '10px';
    toggleButton.style.right = '10px';
    toggleButton.style.zIndex = '1001';
    toggleButton.style.backgroundColor = '#4a4a4a';
    toggleButton.style.color = '#ffffff';
    toggleButton.style.border = 'none';
    toggleButton.style.padding = '10px';
    toggleButton.style.cursor = 'pointer';

    // Create the textarea for notes
    const textarea = document.createElement('textarea');
    textarea.style.width = '100%';
    textarea.style.height = 'calc(100% - 20px)';
    textarea.style.backgroundColor = '#3a3a3a';
    textarea.style.color = '#ffffff';
    textarea.style.border = 'none';
    textarea.style.padding = '10px';
    textarea.style.resize = 'none';
    textarea.style.fontFamily = 'Arial, sans-serif';
    textarea.style.fontSize = '14px';

    // Function to get the character ID from the URL
    function getCharacterId() {
        const pathParts = window.location.pathname.split('/');
        return pathParts.includes('chat') ? pathParts.pop() : null;
    }

    // Load the saved notes from localStorage when character ID is available
    function loadNotes() {
        const characterId = getCharacterId();
        if (characterId) {
            const localStorageKey = `character_notepad_${characterId}`;
            textarea.value = localStorage.getItem(localStorageKey) || '';
        }
    }

    // Save the notes to localStorage whenever the textarea content changes
    textarea.addEventListener('input', () => {
        const characterId = getCharacterId();
        if (characterId) {
            const localStorageKey = `character_notepad_${characterId}`;
            localStorage.setItem(localStorageKey, textarea.value);
        }
    });

    // Add functionality to toggle the panel
    toggleButton.addEventListener('click', () => {
        if (notepadPanel.style.transform === 'translateX(100%)') {
            notepadPanel.style.transform = 'translateX(0)';
        } else {
            notepadPanel.style.transform = 'translateX(100%)';
        }
    });

    // Append elements to the body
    notepadPanel.appendChild(textarea);
    document.body.appendChild(notepadPanel);
    document.body.appendChild(toggleButton);

    // Observe URL changes to update the notepad content
    const observer = new MutationObserver(() => {
        loadNotes();
    });

    observer.observe(document.body, { childList: true, subtree: true });

    // Initial load of notes
    loadNotes();
})();