// ==UserScript==
// @name Better DGG Kick Embed
// @namespace yuniDev.kickembed
// @match https://kick.com/*
// @match https://www.destiny.gg/bigscreen
// @match https://destiny.gg/bigscreen
// @grant GM.registerMenuCommand
// @grant GM.setValue
// @grant GM.getValue
// @version 1.6
// @license MIT
// @author yuniDev
// @run-at document-idle
// @description Slightly hacky solution to embed full kick site instead of the embed. You can toggle kick chat on and off next to the script toggle in your userscript host extension.
// @downloadURL none
// ==/UserScript==
let showChat = false;
GM.getValue("show-chat", "false").then(value => showChat = value === "true");
let insertedFrame = null;
// We need to hide the embed from querySelector("iframe")
class iFrameWrapper extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = ``;
this.iframe = shadowRoot.querySelector('iframe');
}
static get observedAttributes() { return ['src'] };
connectedCallback() { this.updateSrc(); }
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'src') this.updateSrc();
}
updateSrc() {
const src = this.getAttribute('src');
if (src && this.iframe) this.iframe.src = src;
}
}
customElements.define('kick-embed-iframe-wrapper', iFrameWrapper);
function htmlToNode(html) {
const template = document.createElement('template');
template.innerHTML = html;
return template.content.firstChild;
}
function hideFunc(el) {
el.style.display = 'none';
}
function addObserver(selector, func = hideFunc) {
function checkAndHide(obs) {
const elToHide = document.querySelector(selector);
if (elToHide) {
func(elToHide);
obs.disconnect();
}
}
const observer = new MutationObserver((_, obs) => checkAndHide(obs));
observer.observe(document.body, { childList: true, subtree: true });
checkAndHide(observer);
}
function hideSurroundings() {
addObserver("[data-sidebar]", el => {
el.setAttribute("data-sidebar", false);
el.setAttribute("data-theatre", true);
el.setAttribute("data-chat", showChat);
});
addObserver(".z-controls.hidden button", el => el.parentNode.style.display = 'none');
addObserver("#channel-chatroom > div:first-child", el => el.style.display = 'none');
addObserver(".z-modal:has(button[data-testid='accept-cookies'])");
}
function updateEmbed() {
const iframe = document.querySelector("iframe.embed-frame");
if (!iframe) return;
const iframeLocation = iframe.src;
let channel = null;
if (iframeLocation.includes("player.kick")) {
channel = iframeLocation.split('/').pop();
} else if (window.location.hash.startsWith("#kick/")) {
channel = window.location.hash.split('/')[1];
}
if (!channel) return;
iframe.style.display = 'none';
if (insertedFrame) return;
insertedFrame = htmlToNode(``);
iframe.parentNode.appendChild(insertedFrame);
}
function loadDGG(channel) {
document.body.appendChild(htmlToNode(``));
function embedObserver(list, obs) {
for (const mutation of list) {
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
for (const node of mutation.addedNodes) {
if (node.nodeType === Node.ELEMENT_NODE &&
node.tagName === 'IFRAME' &&
node.classList.contains('embed-frame'))
updateEmbed();
}
}
}
}
const observer = new MutationObserver((obj, obs) => embedObserver(obj, obs));
observer.observe(document.getElementById("embed"), { childList: true, subtree: true });
updateEmbed();
function clearObserver() {
observer.disconnect();
removeEventListener('hashchange', clearObserver);
}
addEventListener('hashchange', clearObserver);
}
async function toggleKickChat() {
let showChat = (await GM.getValue("show-chat", "false")) === "true";
showChat = !showChat;
await GM.setValue("show-chat", String(showChat));
const iframe = document.querySelector("iframe.embed-frame");
iframe.contentWindow.postMessage({ type: "yuniDev.kickembed.show-chat", value: showChat }, "*");
}
function setupChatToggleCallback() {
window.addEventListener("message", ({ data }) => {
const { type, value } = data;
if (type == "yuniDev.kickembed.show-chat") {
showChat = value;
document.body.querySelector("[data-sidebar]").setAttribute("data-chat", value);
}
});
}
if (window.location.hostname === "kick.com" && window.self !== window.top) { // Kick inside of iframe
hideSurroundings();
setInterval(() => {
if (![...document.querySelectorAll("nav")].find(el => el.getAttribute("style") && el.getAttribute("style").indexOf("display: none") > -1)) hideSurroundings();
}, 200);
setupChatToggleCallback();
} else if (window.location.pathname === "/bigscreen") {
loadDGG();
addEventListener('hashchange', () => {
insertedFrame?.remove();
insertedFrame = null;
loadDGG();
});
GM.registerMenuCommand("Toggle Kick Chat", toggleKickChat);
}