TriX UI Library

UI library for the TriX Executor. Not intended for direct installation.

Dette script bør ikke installeres direkte. Det er et bibliotek, som andre scripts kan inkludere med metadirektivet // @require https://update.greasyfork.org/scripts/541462/1622887/TriX%20UI%20Library.js

// ==UserScript==
// @name        TriX UI Library
// @namespace   https://github.com/YourUsername/TriX-Executor
// @version     3.1.2
// @description The main user interface for the TriX Executor.
// @author      You
// @license     MIT
// ==/UserScript==

const TriX_UI = (function() {
    'use strict';
    
    let _GM; // To store GM functions

    const UI = {
        isMinimized: false,
        currentScriptName: "",

        init(gmFunctions) {
            _GM = gmFunctions;
            this.injectCSS();
            this.injectHTML();
            this.attachEventListeners();
            TriX_Core.ScriptManager.populateScriptList();
            this.updateTabCountUI(1);
            this.log("TriX UI Library v3.1.2 initialized.");
            this.showTab("js");
            if (typeof TriX_Addons !== 'undefined') {
                TriX_Addons.init(_GM);
            }
        },

        updateTabCountUI(count) {
            const openBtnBadge = document.getElementById('trix-open-btn-badge');
            const headerBadge = document.getElementById('trix-header-tab-counter');
            if (openBtnBadge) openBtnBadge.textContent = count;
            if (headerBadge) headerBadge.textContent = count;
        },

        injectCSS: function() {
            _GM.GM_addStyle(`:root{--trix-bg-primary:#1e1e1e;--trix-bg-secondary:#2d2d2d;--trix-bg-tertiary:#3c3c3c;--trix-accent-color:#00aeff;--trix-text-primary:#d4d4d4;--trix-text-secondary:#8c8c8c;--trix-border-color:#4a4a4a}#trix-container,#trix-open-btn{font-family:'Segoe UI','Roboto',sans-serif!important}#trix-container{position:fixed!important;top:50px!important;left:50px!important;width:600px;height:400px;background-color:var(--trix-bg-primary);border:1px solid var(--trix-border-color);box-shadow:0 0 20px rgba(0,0,0,.5);z-index:1000000!important;display:flex!important;flex-direction:column;resize:both;overflow:hidden;min-width:450px;min-height:300px}#trix-container.hidden{display:none!important}#trix-container.minimized{height:auto!important;min-height:0!important;resize:none!important}#trix-container.minimized #trix-body,#trix-container.minimized #trix-footer,#trix-container.minimized #trix-console{display:none!important}#trix-open-btn{position:fixed!important;top:20px!important;right:20px!important;z-index:999999!important;display:flex!important;align-items:center;background-color:var(--trix-accent-color)!important;color:#fff!important;border:none!important;border-radius:5px;padding:10px 15px!important;cursor:pointer!important;box-shadow:0 0 10px rgba(0,174,255,.7);font-weight:700!important;font-size:14px!important}.trix-tab-badge{display:inline-block;background-color:var(--trix-bg-secondary);color:var(--trix-text-primary);padding:2px 8px;margin-left:8px;border-radius:10px;font-size:12px;font-weight:700;line-height:1.2;vertical-align:middle;min-width:10px;text-align:center}#trix-header{background-color:var(--trix-bg-secondary);padding:5px 10px;cursor:move;user-select:none;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--trix-border-color)}#trix-header-title{display:flex;align-items:center;font-weight:700;color:var(--trix-text-primary)}#trix-logo{width:24px;height:24px;margin-right:8px}#trix-addons-btn-container{flex-grow:1;text-align:center}#trix-addons-btn{display:inline-block;padding:4px 12px;font-size:13px;font-weight:700;background-color:var(--trix-bg-tertiary);border-radius:5px;cursor:pointer;transition:background-color .2s}#trix-addons-btn:hover{background-color:#4a5276}#trix-window-controls{display:flex;align-items:center}#trix-window-controls button{background:0 0;border:none;color:var(--trix-text-secondary);font-size:18px;cursor:pointer;margin-left:10px;padding:0 4px;line-height:1;transition:color .2s}#trix-window-controls button:hover{color:var(--trix-accent-color)}#trix-close-btn:hover{color:#ff5555}#trix-body{flex-grow:1;display:flex;overflow:hidden}#trix-left-panel{width:160px;background-color:var(--trix-bg-secondary);padding:10px 0;display:flex;flex-direction:column;border-right:1px solid var(--trix-border-color)}#trix-script-list-title{padding:0 10px 10px;font-weight:700;color:var(--trix-text-primary);border-bottom:1px solid var(--trix-border-color)}#trix-script-list{flex-grow:1;overflow-y:auto;margin-top:10px}.trix-script-item{padding:8px 15px;cursor:pointer;color:var(--trix-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-left:3px solid transparent}.trix-script-item:hover{background-color:var(--trix-bg-tertiary);color:var(--trix-text-primary)}.trix-script-item.active{border-left:3px solid var(--trix-accent-color);background-color:rgba(0,174,255,.1);color:var(--trix-text-primary)!important;font-weight:700}#trix-right-panel{flex-grow:1;display:flex;flex-direction:column}#trix-editor-tabs{display:flex;background-color:var(--trix-bg-primary);border-bottom:1px solid var(--trix-border-color)}.trix-editor-tab-btn{padding:8px 12px;cursor:pointer;border:none;background-color:transparent;color:var(--trix-text-secondary);font-size:13px;border-bottom:2px solid transparent}.trix-editor-tab-btn.active{color:var(--trix-accent-color);border-bottom-color:var(--trix-accent-color)}.trix-editor-pane{display:none;flex-grow:1;flex-direction:column}.trix-editor-pane.active{display:flex}.trix-editor{flex-grow:1;background-color:var(--trix-bg-primary);color:var(--trix-text-primary);border:none;padding:10px;box-sizing:border-box;resize:none;font-family:'Fira Code',monospace;font-size:14px}#trix-console{height:120px;background-color:var(--trix-bg-secondary);border-top:1px solid var(--trix-border-color);padding:5px;overflow-y:auto;font-size:12px;font-family:'Fira Code',monospace}#trix-console div{padding:2px 8px;border-bottom:1px solid #1e202c;word-break:break-all}#trix-console .log-error{color:#f7768e}#trix-console .log-warn{color:#e0af68}#trix-console .log-info{color:#7dcfff}#trix-console .log-broadcast{color:#9ece6a;font-style:italic}#trix-footer{display:flex;gap:10px;padding:10px;background-color:var(--trix-bg-secondary);border-top:1px solid var(--trix-border-color);align-items:center}.trix-button{background-color:var(--trix-bg-tertiary);border:1px solid var(--trix-border-color);color:var(--trix-text-primary);padding:8px 15px;cursor:pointer;border-radius:5px}.trix-button:hover{background-color:#4a5276}.trix-button.primary{background-color:var(--trix-accent-color);color:#1a1b26;font-weight:700}.trix-button.primary:hover{background-color:#9aadef}.trix-button.danger{background-color:#f7768e;color:#1a1b26}.trix-button.danger:hover{background-color:#f88e9a}`)},
        injectHTML:function(){const e=`<div id="trix-container" class="hidden"><div id="trix-header"><div id="trix-header-title"><img id="trix-logo" src="https://i.postimg.cc/0NkRZxDm/image.png" alt="TriX Logo"> <span id="trix-header-title-text">TriX Executor</span><span id="trix-header-tab-counter" class="trix-tab-badge">1</span></div><div id="trix-addons-btn-container"><span id="trix-addons-btn" title="Addons">Addons +</span></div><div id="trix-window-controls"><button id="trix-minimize-btn" title="Minimize">-</button> <button id="trix-close-btn" title="Close">✕</button></div></div><div id="trix-body"><div id="trix-left-panel"><div id="trix-script-list-title">Script List</div><div id="trix-script-list"></div></div><div id="trix-right-panel"><div id="trix-editor-tabs"><button class="trix-editor-tab-btn" data-tab="js">JavaScript</button><button class="trix-editor-tab-btn" data-tab="python">Python</button></div><div id="js-pane" class="trix-editor-pane"><textarea id="trix-editor" placeholder="-- Paste or load a JavaScript script here..."></textarea></div><div id="python-pane" class="trix-editor-pane"><textarea id="trix-python-editor" class="trix-editor" placeholder="-- Skulpt Python Interpreter --\n-- Note: Libraries like numpy are not supported. --\n\nimport time\n\nprint(\"Hello from Python in the browser!\")\nprint(time.ctime())\n"></textarea></div><div id="trix-console"></div></div></div><div id="trix-footer"><button id="trix-execute-btn" class="trix-button primary">▶ Execute</button> <button id="trix-clear-btn" class="trix-button">Clear</button> <input type="text" id="trix-save-name" placeholder="Script Name..." class="trix-button" style="flex-grow:1; cursor:text;"> <button id="trix-save-btn" class="trix-button">Save</button> <button id="trix-delete-btn" class="trix-button danger">Delete</button></div></div><button id="trix-open-btn"><span>Open TriX</span><span id="trix-open-btn-badge" class="trix-tab-badge">1</span></button>`;document.body.insertAdjacentHTML("beforeend",e)},
        attachEventListeners:function(){const e=document.getElementById("trix-container"),t=document.getElementById("trix-header");t.addEventListener("mousedown",t=>{if(t.target.closest("#trix-window-controls, #trix-addons-btn-container"))return;let i=!0;const s=t.clientX-e.offsetLeft,o=t.clientY-e.offsetTop,n=t=>{i&&(t.preventDefault(),e.style.left=`${t.clientX-s}px`,e.style.top=`${t.clientY-o}px`)},c=()=>{i=!1,document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",c)};document.addEventListener("mousemove",n),document.addEventListener("mouseup",c)}),document.getElementById("trix-open-btn").addEventListener("click",()=>this.togglePanel(!0)),document.getElementById("trix-close-btn").addEventListener("click",()=>this.togglePanel(!1)),document.getElementById("trix-minimize-btn").addEventListener("click",()=>{this.isMinimized=!this.isMinimized,e.classList.toggle("minimized",this.isMinimized)}),document.querySelectorAll(".trix-editor-tab-btn").forEach(e=>{e.addEventListener("click",()=>this.showTab(e.dataset.tab))}),document.getElementById("trix-script-list").addEventListener("click",e=>{if(e.target.matches(".trix-script-item")){TriX_Core.ScriptManager.loadScriptToEditor(e.target.dataset.scriptKey)}}),document.getElementById("trix-execute-btn").addEventListener("click",()=>{const e=document.querySelector(".trix-editor-tab-btn.active").dataset.tab;"js"===e?TriX_Core.Executor.executeJS(document.getElementById("trix-editor").value):"python"===e&&TriX_Core.Executor.executePY(document.getElementById("trix-python-editor").value)}),document.getElementById("trix-clear-btn").addEventListener("click",()=>{document.getElementById("trix-editor").value="",document.getElementById("trix-python-editor").value="",document.getElementById("trix-save-name").value="",this.setActiveScriptItem(null),this.currentScriptName=""}),document.getElementById("trix-save-btn").addEventListener("click",()=>TriX_Core.ScriptManager.saveScriptFromEditor()),document.getElementById("trix-delete-btn").addEventListener("click",()=>TriX_Core.ScriptManager.deleteCurrentScript()),document.getElementById("trix-addons-btn").addEventListener("click",()=>TriX_Addons.show())},
        showTab:function(e){document.querySelectorAll(".trix-editor-pane").forEach(t=>t.classList.remove("active")),document.querySelectorAll(".trix-editor-tab-btn").forEach(t=>t.classList.remove("active")),document.getElementById(`${e}-pane`).classList.add("active"),document.querySelector(`.trix-editor-tab-btn[data-tab="${e}"]`).classList.add("active")},
        togglePanel:function(e){const t=document.getElementById("trix-container"),i=document.getElementById("trix-open-btn"),s=t.classList.contains("hidden");!0===e||s?(t.classList.remove("hidden"),i.style.display="none"):(t.classList.add("hidden"),i.style.display="flex")},log:function(e,t="log"){const i=document.getElementById("trix-console");if(!i)return;const s=document.createElement("div");s.className=`log-${t}`,s.textContent=`> ${String(e)}`,i.prepend(s)},setActiveScriptItem:function(e){document.querySelectorAll(".trix-script-item").forEach(t=>{t.classList.toggle("active",t.dataset.scriptKey===e)})},
    };
    return UI;
})();