您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Fixes some Tinychat room shortcomings and adds useful features.
当前为
// ==UserScript== // @name Tinychat Enhancement Suite (TES) // @namespace https://gf.qytechs.cn/en/users/27283-mutationobserver // @version 2018.06.10v36 // @description Fixes some Tinychat room shortcomings and adds useful features. // @author MutationObserver // @match https://tinychat.com/room/* // @exclude https://tinychat.com/room/*?1 // @grant GM_setValue // @grant GM_getValue // @grant GM_listValues // ==/UserScript== /* jshint -W097 */ var initInterval = setInterval(waitForInit, 500); function waitForInit(){ if (document.querySelector("tinychat-webrtc-app").shadowRoot) { clearInterval(initInterval); (function() { // Actual userscript starts here // browserFirefox = (navigator.userAgent.includes("Firefox/") ? true : false); var bodyElem = document.querySelector("body"); var webappElem = document.querySelector("tinychat-webrtc-app").shadowRoot; var chatlogElem = webappElem.querySelector("tinychat-chatlog").shadowRoot; var titleElem = webappElem.querySelector("tinychat-title").shadowRoot; var sidemenuElem = webappElem.querySelector("tinychat-sidemenu").shadowRoot; var videomoderationElem = sidemenuElem.querySelector("tc-video-moderation").shadowRoot; var videolistElem = webappElem.querySelector("tinychat-videolist").shadowRoot; var chatlistElem = sidemenuElem.querySelector("tinychat-chatlist").shadowRoot; var userlistElem = sidemenuElem.querySelector("tinychat-userlist").shadowRoot; var userContextmenuElem = userlistElem.querySelector("tinychat-user-contextmenu").shadowRoot; var chatlogCSS = chatlogElem.querySelector("#chat-wrapper"); var sidemenuCSS = sidemenuElem.querySelector("#sidemenu"); var videomoderationCSS = videomoderationElem.querySelector("#moderatorlist"); var webappCSS = webappElem.querySelector("#toast"); var chatlistCSS = chatlistElem.querySelector("#header"); var userlistCSS = userlistElem.querySelector("#header"); var userContextmenuCSS = userContextmenuElem.querySelector("#main"); var titleCSS = titleElem.querySelector("#room-header"); var videolistCSS = videolistElem.querySelector("#videolist"); var bodyCSS = document.querySelector("body"); var resourceDirectory = document.querySelector('link[rel="manifest"]').getAttribute("href").split("manifest")[0]; // \/([\d\.\-])+\/ var audioPop = new Audio(resourceDirectory + 'sound/pop.mp3'); var settingMentions = []; var giftsElemWidth = 127; var freshInstall = (GM_listValues().length == 0); var urlAddress = new URL(window.location.href); var urlPars = urlAddress.searchParams; var roomName = document.querySelector("tinychat-webrtc-app").getAttribute("roomname"); document.title = roomName + " - Tinychat"; var userinfoCont = sidemenuElem.querySelector("#user-info > div"); if (userinfoCont.hasAttribute("title")) { bodyCSS.classList.add("logged-in"); sidemenuElem.querySelector("#sidemenu").classList.add("logged-in"); } var settingsQuick = { "Autoscroll" : (GM_getValue("tes-Autoscroll") == "true" || GM_getValue("tes-Autoscroll") == undefined), "MentionsMonitor" : (GM_getValue("tes-MentionsMonitor") == "true" || GM_getValue("tes-MentionsMonitor") == undefined), "NotificationsOff" : (GM_getValue("tes-NotificationsOff") == "true"), "ChangeFont" : (GM_getValue("tes-ChangeFont") == "true" || GM_getValue("tes-ChangeFont") == undefined), "NightMode" : (GM_getValue("tes-NightMode") == "true") }; if (settingsQuick["ChangeFont"]) bodyElem.classList.add("tes-changefont"); if (settingsQuick["NightMode"]) nightmodeToggle(true); if (browserFirefox) { titleElem.querySelector("#room-header-info").insertAdjacentHTML("afterend", ` <div id="tes-firefoxwarning" class="style-scope tinychat-title" style="font-size: .75em; background: white; color: grey; width: 200px; padding: 5px; line-height: 13px;vertical-align: middle;border: #ddd 1px solid;border-width: 0px 1px 0px 1px;"> <div class="style-scope tinychat-title" style="display: table;height: 100%;"> <span style="display: table-cell; vertical-align: middle;top: 16%;" class="style-scope tinychat-title"> Tinychat Enhancement Suite only supports Chrome. Support for Firefox is coming, but for now it only has autoscrolling. </span> </div> </div> `); } function waitForSettings() { if (browserFirefox) { clearInterval(settingsWaitInterval); return; } settingsVisible = false; if (titleElem.querySelector("#room-header-gifts") != null) { clearInterval(settingsWaitInterval); giftsElemWidth = titleElem.querySelector("#room-header-gifts").offsetWidth; if (titleElem.querySelector("#room-header-gifts-items") == null) { giftsElemWidth1000 = giftsElemWidth + 45; } else { giftsElemWidth1000 = giftsElemWidth; } if (titleCSS.querySelector("#titleCSS")) { titleCSS.querySelector("#titleCSS").innerHTML += ` #tes-settings { right: ` + giftsElemWidth + `px; } `; } settingsElem = titleElem.querySelector("#room-header-gifts").insertAdjacentHTML("beforebegin", ` <div id="tes-settings"> <div id="tes-settingsBox" class="hidden"> <p id="title"><a href="https://gf.qytechs.cn/en/scripts/32964-tinychat-enhancement-suite" target="_blank">Tinychat Enhancement Suite</a></p> <div id="tes-settings-mentions" class="tes-setting-container"> <input type="checkbox"> <span class="label"> Alert phrases <span class="info" data-title='A comma-separated list of phrases to alert/highlight for. Example of 3 phrases: "hello,Google Chrome,sky"'>?</span> </span> <div class="inputcontainer"> <input class="text"><button class="save blue-button">save</button> </div> </div> <div id="tes-settings-autoscroll" class="tes-setting-container"> <input type="checkbox"> <span class="label"> Autoscroll </span> </div> <div id="tes-settings-notifications" class="tes-setting-container"> <input type="checkbox"> <span class="label"> Hide notifications </span> </div> <div id="tes-settings-changefont" class="tes-setting-container"> <input type="checkbox"> <span class="label"> Improve font <span class="info" data-title='The default font is too thin in some browsers'>?</span> </span> </div> <div id="tes-settings-nightmode" class="tes-setting-container"> <input type="checkbox"> <span class="label"> Night mode </span> </div> <!-- <div id="tes-settings-messageanim" class="tes-setting-container"> <input type="checkbox"> <span class="label"> Disable message animation </span> </div> --> </div> <div id="tes-updateNotifier"><a class="tes-closeButtonSmall">✕</a><span>New feature: night mode!</span></div> <div id="tes-settingsGear" title="Tinychat Enhancement Suite settings"><span>✱</span></div> </div> `); titleElem.getElementById("tes-settingsGear").addEventListener("click", toggleSettingsDisplay); titleElem.getElementById("tes-updateNotifier").addEventListener("click", function(){toggleSettingsDisplay("updateNotifier");} ); if (!freshInstall && GM_getValue("tes-updateNotifSeen") != "2018.05.30v29") titleElem.getElementById("tes-updateNotifier").classList.add("visible"); titleElem.querySelector("#tes-settings #tes-settings-mentions button.save").addEventListener("click", function(){mentionsManager("save");} ); !browserFirefox ? mentionsManager("load") : void(0); settingsCheckboxUpdate(); titleElem.querySelector("#tes-settings-autoscroll input").addEventListener("click", function(){settingsCheckboxUpdate("tes-settings-autoscroll");}); titleElem.querySelector("#tes-settings-mentions input:first-of-type").addEventListener("click", function(){settingsCheckboxUpdate("tes-settings-mentions");}); titleElem.querySelector("#tes-settings-notifications input:first-of-type").addEventListener("click", function(){settingsCheckboxUpdate("tes-settings-notifications");}); titleElem.querySelector("#tes-settings-changefont input").addEventListener("click", function(){settingsCheckboxUpdate("tes-settings-changefont");}); titleElem.querySelector("#tes-settings-nightmode input").addEventListener("click", function(){settingsCheckboxUpdate("tes-settings-nightmode");}); notificationHider(); } } function nightmodeToggle(arg) { var camQueryString = ".videos-items:last-child > .js-video"; var messageQueryString = "#chat-content .message"; if (arg == true) { bodyElem.classList.add("tes-nightmode"); titleCSS.classList.add("tes-nightmode"); videolistCSS.classList.add("tes-nightmode"); chatlistCSS.classList.add("tes-nightmode"); chatlogCSS.classList.add("tes-nightmode"); chatlogElem.querySelector("#chat-wider").classList.add("tes-nightmode"); // Messages: if (chatlogElem.querySelector(messageQueryString) != null) { var messageElems = chatlogElem.querySelectorAll(messageQueryString); for (i=0; i < messageElems.length; i++) { var messageItem = messageElems[i].querySelector("tc-message-html").shadowRoot; var messageItemCSS = messageItem.querySelector(".message"); messageItemCSS.classList.add("tes-nightmode"); } } // Cams: if (videolistElem.querySelector(camQueryString) != null) { var camElems = videolistElem.querySelectorAll(camQueryString); for (i=0; i < camElems.length; i++) { var camItem = camElems[i].querySelector("tc-video-item").shadowRoot; var camItemCSS = camItem.querySelector(".video"); camItemCSS.classList.add("tes-nightmode"); camItemCSShtml = ` <style id="camItemCSS"> .tes-nightmode.video:after { border-color: #2d373a; } </style> `; if (camItemCSS.querySelector("#camItemCSS") == null) camItemCSS.insertAdjacentHTML("afterbegin", camItemCSShtml); } } } if (arg == false) { bodyElem.classList.remove("tes-nightmode"); titleCSS.classList.remove("tes-nightmode"); videolistCSS.classList.remove("tes-nightmode"); chatlistCSS.classList.remove("tes-nightmode"); chatlogCSS.classList.remove("tes-nightmode"); chatlogElem.querySelector("#chat-wider").classList.remove("tes-nightmode"); // Messages: if (chatlogElem.querySelector(messageQueryString) != null) { var messageElems = chatlogElem.querySelectorAll(messageQueryString); for (i=0; i < messageElems.length; i++) { var messageItem = messageElems[i].querySelector("tc-message-html").shadowRoot; var messageItemCSS = messageItem.querySelector(".message"); messageItemCSS.classList.remove("tes-nightmode"); } } // Cams: if (videolistElem.querySelector(camQueryString) != null) { var camElems = videolistElem.querySelectorAll(camQueryString); for (i=0; i < camElems.length; i++) { var camItem = camElems[i].querySelector("tc-video-item").shadowRoot; var camItemCSS = camItem.querySelector(".video"); camItemCSS.classList.remove("tes-nightmode"); } } } } function toggleSettingsDisplay(arg) { if (arg == "updateNotifier") { titleElem.querySelector("#tes-updateNotifier").classList.remove("visible"); GM_setValue("tes-updateNotifSeen", "2018.05.30v29"); } if (settingsVisible == true) { titleElem.getElementById("tes-settingsBox").classList.add("hidden"); titleElem.getElementById("tes-settings").classList.remove("tes-open"); settingsVisible = false; } else { titleElem.getElementById("tes-settingsBox").classList.remove("hidden"); titleElem.getElementById("tes-settings").classList.add("tes-open"); settingsVisible = true; } } function settingsCheckboxUpdate(settingName=null, value=null) { if (settingName == null && value == null) { titleElem.getElementById("tes-settings-autoscroll").querySelector("input").checked = settingsQuick["Autoscroll"]; titleElem.getElementById("tes-settings-mentions").querySelector("input").checked = settingsQuick["MentionsMonitor"]; titleElem.getElementById("tes-settings-notifications").querySelector("input").checked = settingsQuick["NotificationsOff"]; titleElem.getElementById("tes-settings-changefont").querySelector("input").checked = settingsQuick["ChangeFont"]; titleElem.getElementById("tes-settings-nightmode").querySelector("input").checked = settingsQuick["NightMode"]; return; } if (settingName == "tes-settings-autoscroll") { if (value == null) { var newValue = titleElem.getElementById("tes-settings-autoscroll").querySelector("input").checked; settingsQuick["Autoscroll"] = newValue; GM_setValue("tes-Autoscroll", newValue.toString()); } } if (settingName == "tes-settings-mentions") { if (value == null) { var newValue = titleElem.getElementById("tes-settings-mentions").querySelector("input:first-of-type").checked; // if (newValue) { // titleElem.getElementById("tes-settings-mentions").getAttribute("class").includes("setting-disabled"); // } settingsQuick["MentionsMonitor"] = newValue; GM_setValue("tes-MentionsMonitor", newValue.toString()); } } if (settingName == "tes-settings-notifications") { if (value == null) { var newValue = titleElem.getElementById("tes-settings-notifications").querySelector("input").checked; settingsQuick["NotificationsOff"] = newValue; GM_setValue("tes-NotificationsOff", newValue.toString()); notificationHider(); } } if (settingName == "tes-settings-changefont") { if (value == null) { var newValue = titleElem.getElementById("tes-settings-changefont").querySelector("input").checked; settingsQuick["ChangeFont"] = newValue; GM_setValue("tes-ChangeFont", newValue.toString()); fontToggle(newValue); } } if (settingName == "tes-settings-nightmode") { if (value == null) { var newValue = titleElem.getElementById("tes-settings-nightmode").querySelector("input").checked; settingsQuick["NightMode"] = newValue; GM_setValue("tes-NightMode", newValue.toString()); nightmodeToggle(newValue); } } } var settingsWaitInterval = setInterval(waitForSettings,1000); function fontToggle(arg) { arg ? bodyElem.classList.add("tes-changefont") : bodyElem.classList.remove("tes-changefont"); } function notificationHider() { chatlogContainer = chatlogElem.querySelector("#chat-content"); settingsQuick["NotificationsOff"] ? chatlogContainer.classList.add("tes-notif-off") : chatlogContainer.classList.remove("tes-notif-off"); } function mentionsManager(mode) { var inputElem = titleElem.querySelector("#tes-settings #tes-settings-mentions input.text"); // phrases = inputElem.value.split(","); var phrase = inputElem.value; if (phrase.endsWith(",")) { phrase = phrase.slice(0, -1); } if (phrase.startsWith(",")) { phrase = phrase.slice(1); } if (mode == "save") { GM_setValue("tes-Mentions", phrase); settingMentions = phrase.split(","); inputElem.value = phrase; } if (mode == "load") { var loadedMentions = GM_getValue("tes-Mentions"); if (loadedMentions != undefined) { inputElem.value = loadedMentions; settingMentions = loadedMentions.split(","); } } return; var phrase = phrase.toString(); if (mode == "save") { settingMentions.push(phrases); GM_setValue("tes-Mentions", JSON.stringify(setting_Mentions)); console.log("Mention add:" + phrases); } if (mode == "load") { var mentions = JSON.parse(GM_getValue("tes-Mentions")); console.log("Mention load:" + mentions); settingMentions = mentions; inputElem.value = settingMentions.join(); } } !browserFirefox ? injectCSS() : void(0); function injectCSS(cssName=null) { // Indenting is purposely wrong, for readability var insertPosition = "beforeend"; headElem = document.querySelector("head"); if (browserFirefox) { titleCSS = videolistCSS = chatlistCSS = userlistCSS = userContextmenuCSS = bodyCSS = chatlogCSS = sidemenuCSS = videomoderationCSS = webappCSS = headElem; headElem.querySelector('[scope="tinychat-title"]').innerHTML += ` #room-header { min-height: 10%; max-height: 10%; } `; } browserSpoofedChrome = (headElem.innerHTML.includes("Shady DOM styles for") ? true : false); console.log("Spoofed: " + browserSpoofedChrome); if (cssName == "titleCSS" || cssName == null) { titleCSShtml = ` <style id="titleCSS" scope="tinychat-title"> @keyframes ease-to-left { 0% {right: -50px; opacity: 0;} 100% {right: 0; opacity: 1;} } @keyframes ease-to-right { 0% {right:auto;} 100% {right:0;} } @keyframes ease-to-bottom-21px { 0% {top:-300px; opacity: 0;} 100% {top:0; opacity: 1;} } #tes-header-grabber { position: absolute; top: 88px; right: 50%; background: white; width: 60px; height: 20px; border: #ddd 1px solid; border-radius: 19px; text-align: center; color: #b4c1c5; cursor: pointer; transition: all .4s ease-in-out; } .tes-headerCollapsed #tes-header-grabber { top: 9px; background: #f6f6f6; border-top: 0; z-index: 9; border-radius: 11px; line-height: 11px; border-top-left-radius: 0; border-top-right-radius: 0; height: 12px; } .tes-headerCollapsed:hover #tes-header-grabber { height: 29px; line-height: 43px; } input { border: 1px solid #c4d4dc; line-height: 16px; padding-left: 3px; } .label ~ input { border-bottom-left-radius: 6px; border-top-left-radius: 6px; } input ~ button { border-bottom-right-radius: 6px; border-top-right-radius: 6px; } input[type="button"], button { display: inline; padding: 0 15px; border: 0; box-sizing: border-box; letter-spacing: 1px; font-size: 12px; font-weight: bold; line-height: 20px; text-align: center; transition: .2s; outline: none; } .blue-button { color: #fff; background-color: #41b7ef; } .blue-button:hover { background-color: #54ccf3; } .blue-button:active { background-color: #38a8dd; } .tes-setting-container { line-height: initial; } #tes-settings { color: black; } #tes-settings > div { /*animation: ease-to-bottom-21px .2s ease 0s 1;*/ position: relative; top: 0; height: 100px; } @media screen and (max-width: 1000px) { #tes-settings > div { height: 92px; } } #tes-settings .hidden { display: none; } #tes-settings #title { font-weight: bold; } #tes-settings { transition: all .4s ease-in-out; animation: ease-to-bottom-21px .2s ease 0s 1; /*max-height: 10%;*/ font-size: 11px; flex: none; overflow: hidden; z-index: 9; position: absolute; top: -2px; right: ` + (giftsElemWidth + 10).toString() + `px; } @media screen and (max-width: 1000px) { #tes-settings { right: 37px!important; top: -20px; } #tes-settings.tes-open { top: 6px; } #tes-settingsGear { font-size: 52px!important; } #room-header-gifts-buttons > #give-gift { width: 102px; } } @media screen and (max-width: 600px) { #tes-settings { right: -4px!important; top: 19px; } } #tes-settings:hover { overflow: visible; } #tes-settings-mentions .inputcontainer { float: right; position: relative; top: -3px; } #tes-settingsGear { font-size: 70px; color: #38cd57; color: #53b6ef; float: right; } #tes-settingsGear:hover { cursor: pointer; color: #7ccefe; } .tes-open #tes-settingsGear { background: white; border-bottom-right-radius: 15px; border-top-right-radius: 15px; border: #ddd 1px solid; border-left: 0; /*transition: all .2s linear;*/ } #tes-settingsGear span { display: block; transition: transform 0.4s ease-in-out; } .tes-open #tes-settingsGear span { transform: rotate(-90deg); } #tes-settingsBox { background: white; padding: 0px 10px 0px 10px; float: left; border: #53b6ef 1px solid; border-top-left-radius: 12px; border-bottom-left-radius: 12px; animation: ease-to-left .2s ease 0s 1; right: 0; } #tes-settingsBox.hidden { animation: ease-to-right .2s ease 0s 1; display: visible; /*position: relative; right: -1000px;*/ } /*** Inline with header ***/ #tes-settingsBox { border-bottom-width: 0; border-top-left-radius: 0px; border-bottom-left-radius: 0px; } #tes-settingsGear { display: table; } #tes-settingsGear span { display: table-cell; vertical-align: middle; } /*** ************* ***/ #tes-settings .tes-setting-container input[type=checkbox] { margin: 0; margin-right: 1px; float: left; position: absolute; left: 8px; } #tes-settings .label{ margin-right: 4px; margin-left: 16px; } #tes-settings .info{ margin-left: 3px; color: #0d94e3; font-weight: bold; font-family: Arial; border: #0d94e3 1px solid; border-radius: 16px; height: 1em; width: 1em; text-align: center; display: inline-block; } #tes-settings .info:hover:after{ font-weight: normal; padding: 4px 7px 4px 7px; border-radius: 7px; color: white; background: #61787f; content: attr(data-title); display: inline-block; position: absolute; top: 52px; left: 0; z-index: 9; } /*#tes-settings .label:hover:before{ border: solid; border-color: #61787f transparent; border-width: 0px 6px 6px 6px; top: 10px; content: ""; left: 8%; position: relative; display: inline-block; }*/ #tes-settings a:visited, #tes-settings a:link { text-decoration: none; color: inherit; } #tes-settings a:hover { color: #53b6ef; } #room-header { height: 100px; max-height: unset; min-height: unset; transition: all .4s ease-in-out; } #room-header.tes-headerCollapsed { height: 10px; } #room-header.tes-headerCollapsed:hover { height: 27px; } @media screen and (max-width: 600px) { #room-header { min-height: inherit; max-height: inherit; } } #room-header-info { padding: 0; padding-right: 45px; } #room-header-info-text { height: auto; } @media screen and (max-width: 600px) { #room-header-info-text { height: inherit; } } #room-header-avatar { margin: 2px 10px 0 35px; height: 90px; min-width: 90px; max-width: 90px; transition: all .5s linear; } #room-header-avatar:hover { border-radius: unset; } .tes-headerCollapsed:hover #room-header-avatar:hover { z-index: 9; } #room-header-gifts { padding: 10px 10px; } .tes-headerCollapsed #tes-settingsGear { font-size: 33px; } .tes-headerCollapsed #tes-settings > div { height: fit-content; } .tes-headerCollapsed #tes-settingsBox { border-width: 1px; border-radius: 7px; border-top-right-radius: 0; padding-bottom: 7px; } .tes-headerCollapsed #tes-settings { top: 13px; right: 0; } #tes-settings > div#tes-updateNotifier { top: -200px; margin-right: -33px; float: left; border: #53b6ef 1px solid; border-radius: 8px 0 0px 8px; padding: 5px; padding-right: 32px; height: auto; transition: visibility 0s, opacity 0.5s linear; background: white; } #tes-settings.tes-open > div#tes-updateNotifier { visibility: hidden; opacity: 0; width: 0; height: 0; padding: 0; } #tes-settings > div#tes-updateNotifier:hover { cursor: pointer; } .tes-closeButtonSmall { float: left; padding-right: 5px; color: #41b7ef; padding-left: 5px; } #tes-settings > div#tes-updateNotifier.visible { top: 38px; } .tes-closeButtonSmall:hover { color: #7ccefe; } #room-header.tes-nightmode, .tes-nightmode #tes-header-grabber { background-color: #2d373a; border-color: #3c4a4e; } .tes-nightmode #room-header-info-details > span:after { background-color: #2d373a; } .tes-nightmode #tes-header-grabber { color: #565e61; } .tes-nightmode #room-header-info > h1 { color: #9faaad; } .tes-nightmode #room-header-info > h1:after, .tes-nightmode #room-header-info-text:after { opacity: 0; } .tes-nightmode #room-header-gifts-items { background-color: #313c3f; } .tes-nightmode #room-header-gifts-items > a > img { mix-blend-mode: multiply; } .tes-nightmode #room-header-gifts-items:hover > a > img { mix-blend-mode: unset; } .tes-nightmode #room-header-info-details > a { color: #417186; } .tes-nightmode #tes-settings { color: #98a1a4; } .tes-nightmode #tes-settingsGear { color: #145876; } .tes-nightmode #tes-settingsGear:hover { color: #1c7ca6; } .tes-nightmode #tes-settingsBox, .tes-nightmode .tes-open #tes-settingsGear { background-color: #354245; border-color: #3c4a4e; } .tes-nightmode #tes-settings > div#tes-updateNotifier { border-color: #5d7883; } .tes-nightmode #tes-settings > div#tes-updateNotifier { background-color: #354245; border-color: #145876; } .tes-nightmode input { background: #626b6f; color: #c4c8ca; border-color: #79868b; } .tes-nightmode #tes-settings .info { color: #3986a7; border-color: #3986a7; } .tes-nightmode path { fill: #3986a7; } .tes-nightmode circle { stroke: #3986a7; } @media screen and (max-width: 800px) { .tes-nightmode #room-header-gifts { background-color: #2d373a; } } .tes-nightmode #room-header-gifts-buttons > #upgrade { background-color: #6d551d; } .tes-nightmode #room-header-gifts-buttons > #upgrade:hover { background-color: #776231; } .tes-nightmode #room-header-gifts-buttons > #get-coins { background-color: #3a474b; border-color: #275b72; color: #317490; } .tes-nightmode #room-header-gifts-buttons > #get-coins:hover { background-color: #48626a; color: #5fa9c8; } .tes-nightmode #room-header-gifts-buttons > a { background-color: #275b72; color: #788f97; } .tes-nightmode #room-header-gifts-buttons > #give-gift:hover { background-color: #1a80a2; color: #a3b5d2; } </style> `; titleCSS.insertAdjacentHTML(insertPosition, titleCSShtml); } if (cssName == "videolistCSS" || cssName == null) { videolistCSShtml = ` <style id="videolistCSS" scope="tinychat-videolist"> #videos-header { height: 10px; min-height: 10px; } #Fvideolist * { width: 75%!important; display: contents; float: right; flex-direction: column; } #Fvideos { flex-direction: unset; flex-wrap: unset; } #videos-header > span { line-height: initial; position: relative; top: 1px; background: none; } #videos-header > span > svg { height: 16px; padding: 0; } .js-video { transition: all .4s ease-in-out; } #videolist.tes-nightmode, .tes-nightmode #videos-header { background: #2d373a; } .tes-nightmode.video:after, .tes-nightmode .video:after { border-color: #2d373a; } .tes-nightmode #videos-footer-youtube { background-color: #723e3c; } .tes-nightmode #videos-footer-youtube:hover { background-color: #a83c38; } .tes-nightmode #videos-footer-broadcast, .tes-nightmode #videos-footer-broadcast-wrapper > #videos-footer-submenu-button { background-color: #31684c; color: #519472; } .tes-nightmode #videos-footer-broadcast:hover, .tes-nightmode #videos-footer-broadcast-wrapper > #videos-footer-submenu-button:hover { background-color: #338e5f; color: #82d9ad; } .tes-nightmode #videos-footer-broadcast-wrapper > #videos-footer-submenu-button:before { border-color: #519472 transparent; } .tes-nightmode #videos-footer-broadcast-wrapper > #videos-footer-submenu-button:hover:before { border-color: #82d9ad transparent; } .tes-nightmode #videos-footer-push-to-talk { background-color: #31684c; } .tes-nightmode #videos-footer-push-to-talk path { fill: #82d9ad; } .tes-nightmode #videos-footer-push-to-talk:hover { background-color: #338e5f; } #videos-footer-broadcast-wrapper.active-ptt > #videos-footer-push-to-talk { background-color: #404f54; } #videos-footer-broadcast-wrapper.active-ptt > #videos-footer-push-to-talk path { fill: #74817a; } .tes-nightmode #videos-footer-broadcast-wrapper.active > #videos-footer-broadcast, .tes-nightmode #videos-footer-broadcast-wrapper.active > #videos-footer-submenu-button { background-color: #404f54; color: #74817a; } .tes-nightmode #videos-footer-broadcast-wrapper.active > #videos-footer-submenu-button:before { border-color: #74817a transparent; } .tes-nightmode #videos-header path { fill: #3986a7; } .tes-nightmode #videos-header path[fill="none"] { stroke: #3986a7; fill: none; } .tes-nightmode .videos-header-volume { border-color: #3a474b; } .tes-nightmode #videos-footer-youtube path { fill: #996d6c; } </style> `; videolistCSS.insertAdjacentHTML(insertPosition, videolistCSShtml); } if (cssName == "chatlistCSS" || cssName == null) { chatlistCSShtml = ` <style id="chatlistCSS" scope="tinychat-chatlist"> #chatlist > div > span { padding-left: 1px; } #chatlist > #header { top: 3px; height: auto; } /*** --- this block is in chatlistCSS & userlistCSS --- ***/ .list-item > span > img { right: 13px; left: auto; } .list-item > span[data-status]:before { left: auto; right: 0; } .list-item > span > span { background: none!important; box-shadow: none!important; } /*** --- --- ***/ .close-instant > path { fill: white; } .list-item > span > span { /* gift and close buttons */ right: 16px; } .list-item > span:hover > span { /* gift and close buttons */ right: 16px; background: #2d373a!important; } </style> `; chatlistCSS.insertAdjacentHTML(insertPosition, chatlistCSShtml); } if (cssName == "userlistCSS" || cssName == null) { userlistCSShtml = ` <style id="userlistCSS" scope="tinychat-userlist"> #userlist > div > span { padding-left: 1px; } .list-item > span > span { right: auto; padding: 0 5px; } .list-item > span > .nickname { padding-right: 3px; } /*** --- this block is in chatlistCSS & userlistCSS --- ***/ .list-item > span > img { right: 13px; left: auto; } .list-item > span[data-status]:before { left: auto; right: 0; } .list-item > span > span { background: none; box-shadow: none; } /*** --- --- ***/ .list-item > span > span[data-moderator="1"]:before { filter: hue-rotate(226deg) saturate(4000%); } #userlist > #header { top: auto; height: auto; } #button-banlist { padding: 0 6px; } #userlist .yourname, span[data-user-id="840113"] { color: white!important; } </style> `; userlistCSS.insertAdjacentHTML(insertPosition, userlistCSShtml); } if (cssName == "userContextmenuCSS" || cssName == null) { userContextmenuCSShtml = ` <style id="userContextmenuCSS" scope="tinychat-user-contextmenu"> #main { border: 1px solid rgba(0, 0, 0, .1); } </style> `; userContextmenuCSS.insertAdjacentHTML(insertPosition, userContextmenuCSShtml); } if (cssName == "bodyCSS" || cssName == null) { bodyCSShtml = ` <style id="bodyCSS"> #nav-static-wrapper { width: 2px; opacity: .7; } @media screen and (max-width: 1000px) { #nav-static-wrapper { width: 82px; opacity: 1; } } #content { padding: 0; } body.tes-changefont { font-family: sans-serif; } #header-user { left: 62px; } @media screen and (max-width: 1000px) { #header-user { left: 21px; } } @media screen and (max-width: 600px) { #header-user { left: auto; right: 54px; } } @media screen and (min-width: 1000px) { #menu-icon:hover { opacity: 1; } #menu-icon { top: 4px; left: 19px; height: 12px; width: 109px; font-size: 10px; background: #04caff; border-radius: 6px; opacity: .8; } #menu-icon:after { position: absolute; top: 3px; left: 51px; content: ""; height: 7px; width: 7px; border-width: 2px 2px 0px 0px; border-style: solid; border-color: #fff; box-sizing: border-box; transform: rotate(45deg); transition: .2s; } #menu-icon:hover:after { border-width: 0px 0px 2px 2px; } #menu-icon > svg { opacity: 0; } } body.tes-nightmode { color: #9faaad; } </style> `; bodyCSS.insertAdjacentHTML(insertPosition, bodyCSShtml); } messageCSS = ` .tes-nightmode { color: #9faaad;} .tes-mention-message { color: red; } .tes-nightmode.tes-mention-message { color: #e44a3f; } .tes-nightmode.message.system, .tes-nightmode #chat-content > .message.system { background-color: #313c3f; color: #677174; } `; if (cssName == "chatlogCSS" || cssName == null) { chatlogCSShtml = ` <style id="chatlogCSS" scope="tinychat-chatlog"> #chat-content > .message { padding-bottom: 0; padding-top: 0!important; margin-bottom: 0; min-height: 0px!important; } /* #chat-content > .message:hover { background: rgba(0, 0, 0, 0.03); } */ #chat-content > .message.common { margin-bottom: 5px; } #chat-content > .message.system { padding: 0; } #chat-content.tes-notif-off > .message.system { display: none; } #chat-content.tes-notif-off > .message.system.dontHide { display: initial; } #chat-instant > a:first-child, #chat-content > .message > a:first-child { top: auto; } #chat-position #input:before { background: none; } #chat-instant > a > .avatar, #chat-content > .message > a > .avatar { border-radius: unset; } #timestamp { font-size: 11px; color: silver; /* float: right; */ position: absolute; right: 0; padding-top: 3px; } #chat-content > .message > .nickname { overflow: initial; line-height: initial; } #chat-content div.message.common:last-of-type { margin-bottom: 10px; } .tes-nightmode #chat-content > .message > .nickname[data-status=""], .tes-nightmode #chat-instant > .nickname[data-status=""] { color: #9faaad; } #chat-wrapper.tes-nightmode, .tes-nightmode .on-white-scroll::-webkit-scrollbar-track, .tes-nightmode #textarea, .tes-nightmode #chat-instant { background: #2d373a; color: #9faaad; } .tes-nightmode .on-white-scroll::-webkit-scrollbar-thumb { border-color: #2d373a; } #chat-wrapper.tes-nightmode { border-color: #3c4a4e; } .tes-nightmode #timestamp { color: #4e5f65; } #chat-wider.tes-nightmode { background-color: #3c4a4e; } #chat-wider.tes-nightmode:before { border-color: transparent #636e6e; } .tes-nightmode #input:after { border-color: #3c4a4e; } .tes-nightmode #chat-content > .message.system { background-color: #313c3f; } </style> `; chatlogCSS.insertAdjacentHTML(insertPosition, chatlogCSShtml); } if (cssName == "sidemenuCSS" || cssName == null) { var firefoxCSS = ""; if (browserSpoofedChrome) { firefoxCSS = ` #sidemenu { left: 0!important; } `; } sidemenuCSShtml = ` <style id="sidemenuCSS" scope="tinychat-sidemenu"> #sidemenu { min-width: 162px; max-width: 10%; left: auto; } @media screen and (max-width: 1000px) { #sidemenu { left: -188px; } } #sidemenu-content { padding-left: 2px; } #live-directory-wrapper { padding: 0; } #top-buttons-wrapper { padding: 0; } .logged-in #user-info { padding: 0; height: auto; text-align: center; } #user-info button { opacity: .8; } #user-info:hover button { opacity: 1; } #user-info > a { display: none; } #user-info:hover > a { display: initial; } @media screen and (min-width: 1000px) { #live-directory, #upgrade { height: 23px; line-height: 22px; font-size: 13px; opacity: .8; } #live-directory:before { height: 8px; width: 8px; top: 0px; } #upgrade { margin-top: 4px; } #live-directory:hover, #upgrade:hover { opacity: 1; } } ` + firefoxCSS + `</style> `; sidemenuCSS.insertAdjacentHTML(insertPosition, sidemenuCSShtml); } if (cssName == "videomoderationCSS" || cssName == null) { videomoderationCSShtml = ` <style id="videomoderationCSS" scope="tc-video-moderation"> #moderatorlist { padding-left: 0; } #moderatorlist:hover { position: absolute; background: white; z-index: 1000; width: 300px; min-height: 155px; flex-direction: column; position: absolute; background: rgba(45, 55, 58, 0.8); z-index: 1000; width: 350px; max-height: fit-content!important; left: 15px; border-radius: 13px; border: #47575c 1px solid; } #moderatorlist:after { top: 47px; } </style> `; videomoderationCSS.insertAdjacentHTML(insertPosition, videomoderationCSShtml); } if (cssName == "webappCSS" || cssName == null) { webappCSShtml = ` <style id="webappCSS" scope="tinychat-webrtc-app"> #room { padding: 0; padding-left: 142px; } @media screen and (max-width: 1000px) { :host > #room { padding-left: 82px; } } @media screen and (max-width: 600px) { :host > #room { padding-left: 0; } } </style> `; webappCSS.insertAdjacentHTML(insertPosition, webappCSShtml); } } function injectElements() { headerGrabberParElem = titleElem.querySelector("#room-header"); headerGrabberParElem.insertAdjacentHTML("beforeend", `<div id="tes-header-grabber">▲</div>`); headerGrabberElem = headerGrabberParElem.querySelector("#tes-header-grabber"); headerGrabberElem.addEventListener("click", headerGrabber); } function headerGrabber() { headerGrabberParElem.classList.toggle("tes-headerCollapsed"); headerGrabberParElem.classList.contains("tes-headerCollapsed") ? headerGrabberElem.innerHTML = "▼" : headerGrabberElem.innerHTML = "▲"; } !browserFirefox ? injectElements() : void(0); var scrollbox = chatlogElem.querySelector("#chat"); var unreadbubble = chatlogElem.querySelector("#input-unread"); var autoScrollStatus = true; function updateScroll() { scrollbox.scrollTop = scrollbox.scrollHeight; scrollbox.scrollTop = scrollbox.scrollTop + 5; } function userHasScrolled(e) { var scrollwheelAmount = e.deltaY; if (scrollwheelAmount < 0) { autoScrollStatus = false; } if (autoScrollStatus === false && scrollbox.scrollHeight - scrollbox.scrollTop == scrollbox.offsetHeight) { autoScrollStatus = true; } } function newMessageAdded() { if (autoScrollStatus === true && settingsQuick["Autoscroll"]) { updateScroll(); } timestampAdd(); messageParser(); } function userContextmenuUpdated() { var elemBottom = 0; var topPos = userContextmenuCSS.getBoundingClientRect().top; var elemBottom = topPos + userContextmenuCSS.offsetHeight; if (elemBottom > (window.innerHeight - 82)) { // userContextmenuCSS.style.top = (userContextmenuCSS.style.top - userlistElem.querySelector("#userlist").scrollTop - 200) + "px"; // userContextmenuCSS.style.top = (userlistElem.querySelector("#userlist").scrollTop - window.innerHeight) + "px"; userContextmenuCSS.style.top = (window.innerHeight - 82 - userContextmenuCSS.offsetHeight - 15) + "px"; // console.log("Change: " + userContextmenuCSS.style.top); } // console.log("elemBottom: " + elemBottom + ". Max: " + (window.innerHeight - 82) + ". offsetHeight: " + userContextmenuCSS.offsetHeight + ". New top: " + (window.innerHeight - 82 - userContextmenuCSS.offsetHeight)); } function messageParserCheckCSS() { var messages = chatlogElem.querySelectorAll("#chat-content .message") for (i=0; i < messages.length; i++) { var tcMessageHtmlElem = messages[i].querySelector("tc-message-html").shadowRoot; if (!tcMessageHtmlElem.querySelector("#messageCSS")) tcMessageHtmlElem.appendChild(messageParserAddCSS()); if (settingsQuick["NightMode"]) tcMessageHtmlElem.querySelector("#html").classList.add("tes-nightmode"); } } function messageParserAddCSS(elem=null) { var node = document.createElement("style"); var textnode = document.createTextNode(messageCSS); node.appendChild(textnode); node.setAttribute("id", "messageCSS"); if (elem) { elem.appendChild(node); } else { return node; } } messageCount = 0; function messageParser() { latestMessageElem = chatlogElem.querySelector("#chat-content .message:last-of-type"); var typeSystem = false; if (latestMessageElem != null) { if (latestMessageElem.classList.contains("system")) typeSystem = true; latestMessageElem.setAttribute("id", "msg-"+messageCount); messageCount++; tcMessageHtmlElem = latestMessageElem.querySelector("tc-message-html").shadowRoot; latestMessageContentElem = tcMessageHtmlElem.querySelector("#html"); if (!browserFirefox) { if (!tcMessageHtmlElem.querySelector("#messageCSS")) { messageParserAddCSS(tcMessageHtmlElem); } if (settingsQuick["NightMode"]) latestMessageContentElem.classList.add("tes-nightmode"); } latestMessageContent = latestMessageContentElem.innerHTML; latestMessageContent.includes(" banned ") || latestMessageContent.includes(" kicked ") ? latestMessageElem.classList.add("dontHide") : void(0); if (!browserFirefox && settingsQuick["MentionsMonitor"]) { for (i=0; i < settingMentions.length; i++) { if (latestMessageContent.toLowerCase().includes(settingMentions[i].toLowerCase())) { latestMessageContentElem.classList.add("tes-mention-message"); audioPop.play(); console.log('MENTION: "' + settingMentions[i] + '" : ' + latestMessageContent); break; } } } } } var messagesMO = new MutationObserver(function (e) { if (e[0].addedNodes) newMessageAdded(); }); messagesMO.observe(chatlogElem.querySelector("#chat-content"), { childList: true }); var camsMO = new MutationObserver(function (e) { if (e[0].addedNodes) newCamAdded(); }); camsMO.observe(videolistElem.querySelector(".videos-items:last-child"), { childList: true }); var userContextmenuMO = new MutationObserver(function (e) { if (e[0].addedNodes) userContextmenuUpdated(); }); userContextmenuMO.observe(userContextmenuCSS, { attributes: true }); var chatTextboxMO = new MutationObserver(function (e) { if (e[0].addedNodes) chatboxSwitch(); }); chatTextboxMO.observe(chatlogElem.querySelector("#chat-instant"), { attributes: true, attributeFilter: ['class'], childList: false, characterData: false }); // var x = new MutationObserver(function (e) { // if (e[0].addedNodes) newUserAdded(); // }); // x.observe(userlistElem.querySelector("#userlist"), { childList: true }); // function newUserAdded() { // var latestUser = userlistElem.querySelector("#userlist .list-item:last-of-type"); // latestUser.querySelector(".nickname").innerHTML var scrollboxEvent = scrollbox.addEventListener("wheel", userHasScrolled); var unreadbubble = unreadbubble.addEventListener("click", function(){autoScrollStatus = true;} ); function chatboxSwitch() { messageParserCheckCSS(); } function timestampAdd() { var queryString = "#chat-content div.message.common:last-of-type .nickname"; var SHOW_SECONDS = true; var date = new Date(); var hours = date.getHours(); var minutes = date.getMinutes().toString(); var secs = date.getSeconds().toString(); if (hours > 11) { hours = (hours % 12 || 12); var period = "pm"; } else { var period = "am"; } if (hours == "0") { hours = "12"; } if (minutes == "0") { minutes = "00"; } if (minutes.length == 1) { minutes = "0" + minutes; } if (secs.length == 1) { secs = "0" + secs; } if (SHOW_SECONDS == true) { var timestamp = hours + ":" + minutes + ":" + secs + "" + period; } else { var timestamp = hours + ":" + minutes + period; } if (chatlogElem.querySelector(queryString) != null) { var recentMsgNickname = chatlogElem.querySelector(queryString); recentMsgNickname.insertAdjacentHTML("afterend", "<span id='timestamp'> " + timestamp + "</span>"); } } camsMaxed = null; function newCamAdded() { var queryString = ".videos-items:last-child > .js-video"; if (videolistElem.querySelector(queryString)) var camElems = videolistElem.querySelectorAll(queryString); else return; camsCount = 0; for (i=0; i < camElems.length; i++) { camsCount = i + 1; var camItem = camElems[i].querySelector("tc-video-item").shadowRoot; var camItemCSS = camItem.querySelector(".video"); if (settingsQuick["NightMode"]) camItemCSS.classList.add("tes-nightmode"); else camItemCSS.classList.remove("tes-nightmode"); camItemCSShtml = ` <style id="camItemCSS"> .icon-tes-max { position: absolute; top: -40%; right: 0; z-index: 9; background: none; border: 0; } .icon-tes-max:hover { cursor: pointer; } .icon-tes-max path { fill: #04caff; } .video:hover .icon-tes-max { top: 40%; transition: top .2s ease .2s, left .2s ease .2s, right .2s ease .2s, opacity .2s; } .tes-nightmode.video:after { border-color: #2d373a; } </style> `; if (!camItem.querySelector("#camItemCSS")) camItemCSS.insertAdjacentHTML("afterbegin", camItemCSShtml); var camName = camItem.querySelector(".nickname").getAttribute("title"); camElems[i].setAttribute("id", "camUser-"+camName); // Cam maxing try { if (camItem.querySelector(".icon-tes-max")) { var maxbutton = camItem.querySelector(".icon-tes-max"); maxbutton.parentNode.removeChild(maxbutton); } var camMaxButtonHtml = ` <button class="icon-tes-max" id="maxbutton-` + camName + `"> <svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> <path d="M14.37 12.95l3.335 3.336a1.003 1.003 0 1 1-1.42 1.42L12.95 14.37a8.028 8.028 0 1 1 1.42-1.42zm-6.342 1.1a6.02 6.02 0 1 0 0-12.042 6.02 6.02 0 0 0 0 12.042zM6.012 9.032a.996.996 0 0 1-.994-1.004c0-.554.452-1.003.994-1.003h4.033c.55 0 .994.445.994 1.003 0 .555-.454 1.004-.995 1.004H6.012z" fill-rule="evenodd"></path> <path d="M0 .99C0 .445.444 0 1 0a1 1 0 0 1 1 .99v4.02C2 5.555 1.556 6 1 6a1 1 0 0 1-1-.99V.99z" transform="translate(7 5)" fill-rule="evenodd"></path></svg> </button>`; camItem.querySelector(".icon-resize").insertAdjacentHTML("beforebegin", camMaxButtonHtml); var maxCamVar = function(maxCamVarArg){ maximizeCam(maxCamVarArg); }; camItem.querySelector("#maxbutton-"+camName).addEventListener("click", maxCamVar.bind(this, camName)); if (camsMaxed == camName) { camElems[i].classList.add("tes-maxedCam"); camElems[i].parentElement.classList.add("tes-max"); } if (!videolistElem.querySelector(".tes-maxedCam")) camElems[i].parentElement.classList.remove("tes-max"); camMaxCSShtml = ` <style id="camMaxCSS"> .tes-max .js-video { width: 15%!important; } .tes-max.tes-camCount2 .js-video { width: 30%!important; } .tes-max.tes-camCount10-11 .js-video { width: 14%!important; } .tes-max.tes-camCount12 .js-video { width: 12%!important; } :not(.hidden) + .tes-max.tes-camCount12 .js-video, :not(.hidden) + .tes-max.tes-camCount10-11 .js-video, :not(.hidden) + .tes-max .js-video { width: 30%!important; } :not(.hidden) + .tes-max.tes-camCount2 .js-video { width: 60%!important; } .tes-max .js-video.tes-maxedCam, :not(.hidden) + .tes-max .js-video.tes-maxedCam { width: 70%!important; } </style> `; if (videolistCSS.querySelector("#camMaxCSS")) { var maxcss = videolistCSS.querySelector("#camMaxCSS"); maxcss.parentNode.removeChild(maxcss); } videolistCSS.insertAdjacentHTML("beforeend", camMaxCSShtml); } catch(e) { console.log("TES ERROR newCamAdded: " + e.message); } if (settingsQuick["HideAllCams"] == "true" || urlPars.get("hideallcams") == "") { camItem.querySelector("button.icon-visibility").click(); console.log("Cam hide: " + camName); } } // console.log("camsCount: " + camsCount); } function maximizeCam(camName) { try { if (camName != camsMaxed && camsMaxed != null) { maximizeCam(camsMaxed); maximizeCam(camName); return; } var camElem = videolistElem.querySelector("#camUser-" + camName); if (camElem == null) { camsMaxed = null; return; } if (camElem.classList.contains("tes-maxedCam")) { camElem.classList.remove("tes-maxedCam"); camElem.parentElement.classList.remove("tes-max"); camsMaxed = null; } else { camElem.classList.add("tes-maxedCam"); camElem.parentElement.classList.add("tes-max"); camsMaxed = camName; } if (camsCount == 12) { camElem.parentElement.classList.remove("tes-camCount10-11"); camElem.parentElement.classList.remove("tes-camCount2"); camElem.parentElement.classList.add("tes-camCount12"); } else if (camsCount > 9 && camsCount < 12) { camElem.parentElement.classList.remove("tes-camCount12"); camElem.parentElement.classList.remove("tes-camCount2"); camElem.parentElement.classList.add("tes-camCount10-11"); } else if (camsCount == 2) { camElem.parentElement.classList.remove("tes-camCount12"); camElem.parentElement.classList.remove("tes-camCount10-11"); camElem.parentElement.classList.add("tes-camCount2"); } else { camElem.parentElement.classList.remove("tes-camCount12"); camElem.parentElement.classList.remove("tes-camCount10-11"); camElem.parentElement.classList.remove("tes-camCount2"); } } catch(e) { console.log("TES ERROR maximizeCam: " + e.message); } } // Userscript ends here // })(); } else { console.log("Waiting for init..."); } }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址