From 5c0014012b0f1174a06606aaac52ef78f3fb9f13 Mon Sep 17 00:00:00 2001 From: Rodrigo Emanuel Date: Sat, 24 May 2025 02:43:25 -0300 Subject: [PATCH] Add files via upload --- chat.html | 4 +++ css/app.css | 59 ++++++++++++++++++++++++++++++++ js/app-mockup.js | 2 +- js/app.js | 88 +++++++++++++++++++++++++++++++++++++++++++++++- js/commands.json | 29 ++++++++++++++++ 5 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 js/commands.json diff --git a/chat.html b/chat.html index 04d682e..b441847 100644 --- a/chat.html +++ b/chat.html @@ -50,7 +50,11 @@
+ +
+
+
diff --git a/css/app.css b/css/app.css index 657db03..c0be1bb 100644 --- a/css/app.css +++ b/css/app.css @@ -683,6 +683,65 @@ body { } + + +#chat-autocomplete-list { + position: absolute; + bottom: 65px; + left: 10px; + width: calc(100% - 40px); + border-radius: 10px; + background: #222; + color: #FFF; + + max-height: 300px; + overflow: hidden; + overflow-y: visible; + + font-size: 14px;; + + color: #696969; +} + +#chat-autocomplete-list::-webkit-scrollbar { width: 10px; } +#chat-autocomplete-list::-webkit-scrollbar-track { background: #1e1e1e; } +#chat-autocomplete-list::-webkit-scrollbar-thumb { background-color: #555; border-radius: 10px; border: 2px solid #1e1e1e; } +#chat-autocomplete-list::-webkit-scrollbar-thumb:hover { background-color: #777; } + +#chat-autocomplete-list div { + margin: 5px 10px; + padding: 5px; + border-radius: 5px; + cursor: pointer; +} + +#chat-autocomplete-list div.autocomplete-item { + cursor: pointer; + transition: all ease-in-out 300ms; +} + +#chat-autocomplete-list div:not(.autocomplete-item) { + background: #191919; + color: #FFF; + padding: 10px; + margin: 10px; +} + +#chat-autocomplete-list .autocomplete-item strong { + display: block; +} + +#chat-autocomplete-list .autocomplete-item:hover, +#chat-autocomplete-list .autocomplete-item.active { + color: #FFF; + background: #292929; +} + +#chat-autocomplete-list .autocomplete-item small { + color: #666; +} + + #statistics { position: fixed; z-index: 11; diff --git a/js/app-mockup.js b/js/app-mockup.js index 5e7a0d6..49e258e 100644 --- a/js/app-mockup.js +++ b/js/app-mockup.js @@ -1014,4 +1014,4 @@ function randomString(length) { function randomColor() { const randomColor = "hsl(" + Math.random() * 360 + ", 100%, 75%)"; return randomColor; -} +} \ No newline at end of file diff --git a/js/app.js b/js/app.js index 6ec1187..9f1d8f2 100644 --- a/js/app.js +++ b/js/app.js @@ -404,6 +404,7 @@ function hexToRGBA(hexadecimal,opacity) { const chatInputConfig = document.getElementById("chat-input-config"); const chatInputSend = document.getElementById("chat-input-send"); const chatInputForm = document.querySelector("#chat-input form"); +const chatInput = chatInputForm.querySelector("input[type=text]") const settings = document.getElementById("chat-input-settings"); chatInputForm.addEventListener("submit", function(event) { @@ -500,7 +501,6 @@ async function executeModCommand(event, command) { event.preventDefault(); if (streamerBotConnected == true) { - const chatInput = chatInputForm.querySelector("input[type=text]") chatInput.value = command; chatInputForm.requestSubmit(); @@ -537,3 +537,89 @@ document.addEventListener("DOMContentLoaded", () => { }); }); }); + + + + + + +let chatcommands = {}; +let chatcurrentFocus = -1; + +fetch('js/commands.json') +.then(response => response.json()) +.then(data => { + chatcommands = data; +}); + +const chatcommandslist = document.getElementById('chat-autocomplete-list'); + +chatInput.addEventListener('input', function () { + const value = this.value.trim(); + chatcommandslist.innerHTML = ''; + chatcurrentFocus = -1; + if (!value.startsWith('/')) return; + Object.entries(chatcommands).forEach(([groupName, commands]) => { + + const filtered = commands.filter(cmd => cmd.name.startsWith(value)); + + if (filtered.length === 0) return; + + const groupTitle = document.createElement('div'); + groupTitle.textContent = groupName; + chatcommandslist.appendChild(groupTitle); + filtered.forEach(cmd => { + const item = document.createElement('div'); + item.classList.add('autocomplete-item'); + item.innerHTML = `${cmd.name} ${cmd.usage}`; + item.addEventListener('click', () => { + chatInput.value = cmd.name + ' '; + chatcommandslist.innerHTML = ''; + }); + chatcommandslist.appendChild(item); + }); + }); +}); + + +chatInput.addEventListener('keydown', function (e) { + const items = chatcommandslist.querySelectorAll('.autocomplete-item'); + + if (items.length === 0) return; + + if (e.key === 'ArrowDown') { + chatcurrentFocus++; + highlightItem(items); + } + else if (e.key === 'ArrowUp') { + chatcurrentFocus--; + highlightItem(items); + } + + else if (e.key === 'Enter') { + e.preventDefault(); + if (chatcurrentFocus > -1 && items[chatcurrentFocus]) { + items[chatcurrentFocus].click(); + } + } +}); + + +function highlightItem(items) { + if (!items) return; + + items.forEach(item => item.classList.remove('active')); + + if (chatcurrentFocus >= items.length) chatcurrentFocus = 0; + if (chatcurrentFocus < 0) chatcurrentFocus = items.length - 1; + + items[chatcurrentFocus].classList.add('active'); + items[chatcurrentFocus].scrollIntoView({ block: "nearest" }); +} + + +document.addEventListener('click', function (e) { + if (e.target !== chatcommandslist) { + chatcommandslist.innerHTML = ''; + } +}); \ No newline at end of file diff --git a/js/commands.json b/js/commands.json new file mode 100644 index 0000000..4b689eb --- /dev/null +++ b/js/commands.json @@ -0,0 +1,29 @@ +{ + "Twitch" : [ + { "name" : "/me", "usage" : "[message]" }, + { "name" : "/announce", "usage" : "[message]" }, + { "name" : "/clear", "usage" : "" }, + { "name" : "/slow", "usage" : "[duration]" }, + { "name" : "/slowoff", "usage" : "" }, + { "name" : "/subscribers", "usage" : "" }, + { "name" : "/subscribersoff", "usage" : "" }, + { "name" : "/commercial", "usage" : "[duration]" }, + { "name" : "/timeout", "usage" : "[user] [duration] [reason]" }, + { "name" : "/untimeout", "usage" : "" }, + { "name" : "/ban", "usage" : "[user] [duration] [reason]" }, + { "name" : "/unban", "usage" : "" }, + { "name" : "/mod", "usage" : "[user]" }, + { "name" : "/unmod", "usage" : "[user]" }, + { "name" : "/vip", "usage" : "[user]" }, + { "name" : "/unvip", "usage" : "[user]" }, + { "name" : "/shoutout", "usage" : "[user]" }, + { "name" : "/raid", "usage" : "[user]" }, + { "name" : "/unraid", "usage" : "" } + ], + "YouTube" : [ + { "name" : "/yt/title", "usage" : "[title]" }, + { "name" : "/yt/description", "usage" : "[description]" }, + { "name" : "/yt/timeout", "usage" : "[user] [duration]" }, + { "name" : "/yt/ban", "usage" : "[user]" } + ] +} \ No newline at end of file