StumbleChat - Broadcasting User Counter

Track the number of users broadcasting in chat room.

// ==UserScript==
// @name         StumbleChat - Broadcasting User Counter
// @namespace    https://greasyfork.org/en/users/1362976-gitgud
// @version      1.0
// @description  Track the number of users broadcasting in chat room.
// @author       gitgud
// @license      GNU GPLv3
// @match        https://stumblechat.com/room/*
// @grant        none
// ==/UserScript==
    
(function() {
    'use strict';
    
    function debounce(func, wait) {
        let timeout;
        return function(...args) {
            const context = this;
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(context, args), wait);
        };
    }
    
    function countBroadcastingUsers() {
        let broadcastingCount = 0;
        const userList = document.querySelectorAll('#userlist .bar');
    
        userList.forEach(user => {
            const statusDiv = user.querySelector('.status');
            const videoBadge = statusDiv.querySelector('.video_badge:not(.hidden)');
            const audioBadge = statusDiv.querySelector('.audio_badge:not(.hidden)');
            const videoBadgeHide = statusDiv.querySelector('.video_badge_hide:not(.hidden)');
            const audioBadgeHide = statusDiv.querySelector('.audio_badge_hide:not(.hidden)');
    
            if (videoBadge || audioBadge || videoBadgeHide || audioBadgeHide) {
                broadcastingCount++;
            }
        });
    
        return broadcastingCount;
    }
    
    function updateDisplay() {
        const onlineCountSpan = document.getElementById('onlinecount');
        if (onlineCountSpan) {
            const broadcastingCount = countBroadcastingUsers();
            const broadcastingText = ` (${broadcastingCount} broadcasting)`;
            onlineCountSpan.innerHTML = onlineCountSpan.innerHTML.split(' (')[0] + broadcastingText;
        }
    }
    
    const debouncedUpdateDisplay = debounce(updateDisplay, 500);
    
    function startDynamicUpdates() {
        const dynamicObserver = new MutationObserver(debouncedUpdateDisplay);
        dynamicObserver.observe(document.getElementById('userlist'), { childList: true, subtree: true, attributes: true, attributeFilter: ['class'] });
    
        window.addEventListener('beforeunload', () => {
            dynamicObserver.disconnect();
        });
    }
    
    updateDisplay();
    
    startDynamicUpdates();
    
    const interval = setInterval(() => {
        const modalBack = document.querySelector('#modal-back');
        if (modalBack && modalBack.classList.contains('visible')) {
            clearInterval(interval);
            updateDisplay();
        }
    }, 1000);
    
    window.addEventListener('beforeunload', () => {
        clearInterval(interval);
    });
})();