Makes stumblechat webcams 320x240
- // ==UserScript==
- // @name Small Cams Stumblechat
- // @namespace http://tampermonkey.net/
- // @version 0.8
- // @description Makes stumblechat webcams 320x240
- // @author You
- // @match https://stumblechat.com/*
- // @grant GM_addStyle
- // @license none
- // ==/UserScript==
- (function() {
- 'use strict';
- console.log("Script started.");
- // Add styles using GM_addStyle for compacting video wrappers and camera badges
- let css = `
- #videos-content {
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- }
- .videos-items > .js-video {
- width: 100%;
- }
- .video-wrapper {
- position: relative;
- width: 100%;
- height: 100%;
- }
- #regularvideos {
- display: grid;
- grid-template-columns: repeat(5, 320px); // 5 columns of 320px each
- grid-template-rows: repeat(5, 240px); // 5 rows of 240px each
- gap: 5px;
- width: 100%;
- height: 100%;
- }
- .video-cell {
- box-sizing: border-box;
- position: relative;
- }
- .video-badge {
- width: 16px;
- height: 16px;
- background-image: url(../styles/svg/webcam.svg);
- background-position: center center;
- background-repeat: no-repeat;
- position: absolute;
- top: 5px;
- left: 5px;
- }
- `;
- if (typeof GM_addStyle !== "undefined") {
- GM_addStyle(css);
- } else {
- let styleNode = document.createElement("style");
- styleNode.appendChild(document.createTextNode(css));
- (document.querySelector("head") || document.documentElement).appendChild(styleNode);
- }
- // Create a 5x5 grid table for webcam videos
- const videosContent = document.getElementById("videos-content");
- // Adjust positioning of the videos-content div
- videosContent.style.position = 'absolute';
- videosContent.style.bottom = '0';
- videosContent.style.left = '0';
- videosContent.style.width = '100%';
- const table = document.createElement("table");
- table.style.borderCollapse = 'collapse';
- table.style.width = '100%';
- // Create rows and cells in a 5x5 grid (320x240 per cell)
- for (let i = 0; i < 5; i++) {
- const row = document.createElement("tr");
- for (let j = 0; j < 5; j++) {
- const cell = document.createElement("td");
- cell.style.padding = '5px';
- cell.style.textAlign = 'center';
- cell.style.border = '1px solid #ddd';
- cell.style.height = '240px';
- cell.style.width = '320px';
- cell.classList.add('video-cell');
- row.appendChild(cell);
- }
- table.appendChild(row);
- }
- // Insert the table into the "regularvideos" div inside the "videos-content" container
- const regularVideosDiv = videosContent.querySelector("#regularvideos");
- if (!regularVideosDiv) {
- console.error("Could not find #regularvideos container.");
- return;
- }
- regularVideosDiv.appendChild(table);
- // Function to find the first empty cell in the grid
- function findEmptyCell() {
- const cells = table.getElementsByTagName("td");
- for (let cell of cells) {
- if (!cell.hasChildNodes()) {
- return cell;
- }
- }
- return null; // If no empty cells are found
- }
- // Function to add the camera badge
- function addCameraBadge(userElement) {
- const videoBadge = document.createElement('div');
- videoBadge.classList.add('video-badge');
- const statusElement = userElement.querySelector('.status');
- if (statusElement) {
- statusElement.appendChild(videoBadge); // Append it to the user's status element
- }
- }
- // MutationObserver to monitor DOM for video-wrapper additions
- const observer = new MutationObserver(mutations => {
- mutations.forEach(mutation => {
- mutation.addedNodes.forEach(node => {
- if (node.nodeType === 1 && node.classList.contains('js-video') && !node.classList.contains('hidden')) {
- console.log("New video-wrapper detected:", node);
- // Modify the video element within the wrapper
- const videoElement = node.querySelector('video');
- if (videoElement) {
- console.log("Video element found:", videoElement);
- // Find an empty cell in the 5x5 grid and place the entire video wrapper
- const emptyCell = findEmptyCell();
- if (emptyCell) {
- console.log("Placing video wrapper in empty cell...");
- // Move the entire js-video element into the table cell
- emptyCell.appendChild(node);
- // Ensure the video takes up 100% of the cell's width and height
- videoElement.style.width = '100%';
- videoElement.style.height = '100%';
- // Adjust video wrapper styles if needed
- const videoWrapper = node.querySelector('.video-wrapper');
- if (videoWrapper) {
- videoWrapper.style.width = '100%';
- videoWrapper.style.height = '100%';
- }
- // Add camera badge if the user has their camera on
- const userElement = node.closest('.user-item'); // Replace with the correct selector for user elements
- const cameraStatus = userElement ? userElement.getAttribute('data-camera-status') : null; // Replace with the appropriate attribute or logic
- if (cameraStatus === 'active') { // Check if camera is active
- addCameraBadge(userElement);
- }
- }
- } else {
- console.warn("No video element found inside video-wrapper.");
- }
- }
- });
- });
- });
- // Start observing the DOM
- const targetNode = document.body;
- const config = { childList: true, subtree: true };
- observer.observe(targetNode, config);
- console.log("Observer initialized. Watching for js-video elements.");
- // Adding placeholder if needed (ensure vertical <br> appears in empty cells)
- function addPlaceholders() {
- const cells = table.getElementsByTagName("td");
- for (let cell of cells) {
- if (!cell.hasChildNodes()) {
- const placeholder = document.createElement('br');
- cell.appendChild(placeholder);
- }
- }
- }
- // Periodically check for empty cells and add placeholders
- setInterval(addPlaceholders, 1000);
- })();