Crushon.ai Character Circle Counter

Dynamic Character counter for CrushOn.ai

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         Crushon.ai Character Circle Counter
// @namespace    http://tampermonkey.net/
// @version      2.6
// @description  Dynamic Character counter for CrushOn.ai
// @author       Discord: @Squishything (functionality) and @alphawuff (minor styling)
// @match        https://crushon.ai/character*
// @grant        none
// @license      none
// ==/UserScript==

(function () {
    'use strict';

    function addCharacterCounter() {
        const textarea = document.querySelector('textarea');
        if (!textarea) {
            setTimeout(addCharacterCounter, 500);
            return;
        }

        if (document.querySelector('.circle-counter-container')) return;

        const container = document.createElement('div');
        container.className = 'circle-counter-container';
        container.style.position = 'relative';
        container.style.width = '40px';
        container.style.height = '40px';
        container.style.marginTop = '10px';
        container.style.display = 'flex';
        container.style.alignItems = 'center';
        container.style.justifyContent = 'center';
        container.style.pointerEvents = 'none';

        const svgNS = "http://www.w3.org/2000/svg";
        const svg = document.createElementNS(svgNS, "svg");
        svg.setAttribute("width", "40");
        svg.setAttribute("height", "40");
        svg.style.transform = "rotate(-90deg)";

        const r = 20;
        const cx = 20;
        const cy = 20;
        const strokeWidth = 3;
        const circumference = 2 * Math.PI * r;

        const bgCircle = document.createElementNS(svgNS, "circle");
        bgCircle.setAttribute("cx", cx);
        bgCircle.setAttribute("cy", cy);
        bgCircle.setAttribute("r", r);
        bgCircle.setAttribute("stroke", "#444");
        bgCircle.setAttribute("stroke-width", strokeWidth);
        bgCircle.setAttribute("fill", "none");

        const progressCircle = document.createElementNS(svgNS, "circle");
        progressCircle.setAttribute("cx", cx);
        progressCircle.setAttribute("cy", cy);
        progressCircle.setAttribute("r", r);
        progressCircle.setAttribute("stroke", "green");
        progressCircle.setAttribute("stroke-width", strokeWidth);
        progressCircle.setAttribute("fill", "none");
        progressCircle.setAttribute("stroke-dasharray", circumference.toString());
        progressCircle.setAttribute("stroke-dashoffset", circumference.toString());
        progressCircle.style.transition = 'stroke-dashoffset 0.3s ease, stroke 0.3s ease';

        const text = document.createElement('div');
        text.className = 'circle-counter-text';
        text.style.position = 'absolute';
        text.style.fontSize = '10px';
        text.style.fontWeight = 'bold';
        text.style.color = 'white';
        text.style.textShadow = '0px 0px 3px green';
        text.textContent = '0';

        svg.appendChild(bgCircle);
        svg.appendChild(progressCircle);
        container.appendChild(svg);
        container.appendChild(text);

        // Insert directly after the textarea
        textarea.parentNode.insertBefore(container, textarea.nextSibling);

        function resetCounter() {
              if(textarea.value.length < 3000){
                   setTimeout(function() {
                      text.textContent = '0';
                      text.style.color = 'white';
                      text.style.textShadow = '0px 0px 3px white';
                      const offset = circumference * (1 - 0);
                      progressCircle.setAttribute("stroke-dashoffset", offset.toString());
                      //textarea.value = '';
                  }, 500);
              }
            }

            textarea.addEventListener('change', function() {
                resetCounter();
            });

        function updateCircleCounter() {
            const count = textarea.value.length;
            const max = 3000;
            const warning = 2800;

            const percent = Math.min(count / max, 1);
            const offset = circumference * (1 - percent);
            progressCircle.setAttribute("stroke-dashoffset", offset.toString());
            text.textContent = count.toString();

            if (count > warning) {
                progressCircle.setAttribute("stroke", "red");
                text.style.color = 'orange';
                text.style.textShadow = '0 0 4px red';
            } else {
                progressCircle.setAttribute("stroke", "green");
                text.style.color = 'white';
                text.style.textShadow = '0 0 3px green';
            }
        }

        textarea.addEventListener('input', updateCircleCounter);

        let lastUrl = location.href;
        new MutationObserver(() => {
            const url = location.href;
            if (url !== lastUrl) {
                lastUrl = url;
                addCharacterCounter();
            }
        }).observe(document, { subtree: true, childList: true });

        updateCircleCounter();
    }

    window.addEventListener('load', addCharacterCounter);
})();