Greasy Fork 还支持 简体中文。

[TORN] Better Chat

Improvements to the usability of chats 2.0.

Устаревшая версия за 23.10.2023. Перейдите к последней версии.

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

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         [TORN] Better Chat
// @namespace    dekleinekobini.betterchat
// @license      none
// @version      0.1
// @description  Improvements to the usability of chats 2.0.
// @author       DeKleineKobini [2114440]
// @match        https://www.torn.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @run-at       document-body
// @grant        GM_addStyle
// ==/UserScript==

"use strict";

const settings = {
    messages: {
        hideAvatars: true,
        compact: true,
        fixLongName: true,
        leftAlignedText: true, // left align all text, prefixed by the name (supports the mini-profile as well), even for private chats
    },
    box: {
        groupRight: true, // opening chat logic to put private chat left of group chats
        hideAvatars: true,
    },
};

/*
    chat name colours
    return hyperlink capability
    timestamps - multiple toggles of a) timestamp on hover b) timestamp before name and c) no timestamp
*/

(() => {
    setupStyles();
    setupChatModifier();
})();

function includeStyle(styleRules) {
    if (typeof GM_addStyle !== "undefined") {
        GM_addStyle(styleRules);
    } else {
        const styleElement = document.createElement("style");
        styleElement.setAttribute("type", "text/css");
        styleElement.innerHTML = styleRules;
        document.head.appendChild(styleElement);
    }
}

function setupStyles() {
    if (settings.messages.hideAvatars) {
        includeStyle(`
            [class*='chat-box-body__avatar___'] {
                display: none;
            }
        `);
    }
    if (settings.messages.compact) {
        includeStyle(`
            [class*='chat-box-body__sender-group___'] {
                margin-right: 0 !important;
            }

            [class*='chat-box-body__wrapper___'] {
                margin-bottom: 0px !important;
            }

            [class*='chat-box-body___'] > div:last-child {
                margin-bottom: 8px !important;
            }
        `);
    }
    if (settings.messages.fixLongName) {
        includeStyle(`
            [class*='chat-box-body__sender-button___'] {
                max-width: unset !important;
            }
        `);
    }
    if (settings.box.groupRight) {
        includeStyle(`
            [class*='group-chat-box___'] {
                gap: 3px;
            }

            [class*='group-chat-box__chat-box-wrapper___'] {
                margin-right: 0 !important;
            }
        `);
    }

    if (settings.messages.leftAlignedText) {
        includeStyle(`
            [class*='chat-box-body__sender___'] {
                display: unset !important;
                font-weight: 700;
            }

            [class*='chat-box-body__sender-separator___'] {
                display: unset !important;
                margin-right: 4px;
            }

            [class*='chat-box-body__message-box___'] {
                background: none !important;
                border-radius: none !important;
                color: initial !important;
                padding: 0 !important;
            }

            [class*='chat-box-body__message-box--self___'] {
                background: none !important;
                border-radius: none !important;
                color: initial !important;
                padding: 0 !important;
            }

            [class*='chat-box-body__wrapper--self___'] {
                justify-content: normal !important;
            }

            [class*='chat-box-body__wrapper--self___'] > [class*='chat-box-body__message___'],
            [class*='chat-box-body__message___'] {
                color: var(--chat-text-color) !important;
            }
        `);
    }

    if (settings.box.hideAvatars) {
        includeStyle(`
            [class*='avatar__avatar-status-wrapper___'] > img {
                display: none;
            }
        `);
    }
}

async function setupChatModifier() {
    const group = await new Promise((resolve) => {
        new MutationObserver((_, observer) => {
            const group = findByClass(document, "group-chat-box___");
            if (group) {
                observer.disconnect();
                resolve(group);
            }
        }).observe(document, {childList: true, subtree: true});
    });

    group.childNodes.forEach(processChat)
    new MutationObserver((mutations) => {
        mutations.flatMap((mutation) => [...mutation.addedNodes]).forEach(processChat);
    }).observe(group, {childList: true});
}

function processChat(chatNode) {
    if (settings.box.groupRight) {
        const avatarElement = findByClass(chatNode, "chat-box-header__avatar___", "> *");
        const isGroup = avatarElement.tagName.toLowerCase() === "svg";

        if (isGroup) {
            chatNode.style.order = "1";
        }
    }

    const bodyElement = findByClass(chatNode, "chat-box-body___");
    bodyElement.childNodes.forEach(processMessage);
    new MutationObserver((mutations) => {
        mutations.flatMap((mutation) => [...mutation.addedNodes]).forEach(processMessage);
    }).observe(chatNode, {childList: true});
    new MutationObserver(() => {
        bodyElement.childNodes.forEach(processMessage);
    }).observe(bodyElement, {childList: true});
}

function processMessage(messageNode) {
    // TODO - Handle message here if needed.
}

function findByClass(node, className, subSelector = "") {
    return node.querySelector(`[class*='${className}'] ${subSelector}`.trim())
}