🏠 Home 

Small Cams Stumblechat

Makes stumblechat webcams 320x240


Install this script?
  1. // ==UserScript==
  2. // @name Small Cams Stumblechat
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.8
  5. // @description Makes stumblechat webcams 320x240
  6. // @author You
  7. // @match https://stumblechat.com/*
  8. // @grant GM_addStyle
  9. // @license none
  10. // ==/UserScript==
  11. (function() {
  12. 'use strict';
  13. console.log("Script started.");
  14. // Add styles using GM_addStyle for compacting video wrappers and camera badges
  15. let css = `
  16. #videos-content {
  17. position: absolute;
  18. bottom: 0;
  19. left: 0;
  20. width: 100%;
  21. }
  22. .videos-items > .js-video {
  23. width: 100%;
  24. }
  25. .video-wrapper {
  26. position: relative;
  27. width: 100%;
  28. height: 100%;
  29. }
  30. #regularvideos {
  31. display: grid;
  32. grid-template-columns: repeat(5, 320px); // 5 columns of 320px each
  33. grid-template-rows: repeat(5, 240px); // 5 rows of 240px each
  34. gap: 5px;
  35. width: 100%;
  36. height: 100%;
  37. }
  38. .video-cell {
  39. box-sizing: border-box;
  40. position: relative;
  41. }
  42. .video-badge {
  43. width: 16px;
  44. height: 16px;
  45. background-image: url(../styles/svg/webcam.svg);
  46. background-position: center center;
  47. background-repeat: no-repeat;
  48. position: absolute;
  49. top: 5px;
  50. left: 5px;
  51. }
  52. `;
  53. if (typeof GM_addStyle !== "undefined") {
  54. GM_addStyle(css);
  55. } else {
  56. let styleNode = document.createElement("style");
  57. styleNode.appendChild(document.createTextNode(css));
  58. (document.querySelector("head") || document.documentElement).appendChild(styleNode);
  59. }
  60. // Create a 5x5 grid table for webcam videos
  61. const videosContent = document.getElementById("videos-content");
  62. // Adjust positioning of the videos-content div
  63. videosContent.style.position = 'absolute';
  64. videosContent.style.bottom = '0';
  65. videosContent.style.left = '0';
  66. videosContent.style.width = '100%';
  67. const table = document.createElement("table");
  68. table.style.borderCollapse = 'collapse';
  69. table.style.width = '100%';
  70. // Create rows and cells in a 5x5 grid (320x240 per cell)
  71. for (let i = 0; i < 5; i++) {
  72. const row = document.createElement("tr");
  73. for (let j = 0; j < 5; j++) {
  74. const cell = document.createElement("td");
  75. cell.style.padding = '5px';
  76. cell.style.textAlign = 'center';
  77. cell.style.border = '1px solid #ddd';
  78. cell.style.height = '240px';
  79. cell.style.width = '320px';
  80. cell.classList.add('video-cell');
  81. row.appendChild(cell);
  82. }
  83. table.appendChild(row);
  84. }
  85. // Insert the table into the "regularvideos" div inside the "videos-content" container
  86. const regularVideosDiv = videosContent.querySelector("#regularvideos");
  87. if (!regularVideosDiv) {
  88. console.error("Could not find #regularvideos container.");
  89. return;
  90. }
  91. regularVideosDiv.appendChild(table);
  92. // Function to find the first empty cell in the grid
  93. function findEmptyCell() {
  94. const cells = table.getElementsByTagName("td");
  95. for (let cell of cells) {
  96. if (!cell.hasChildNodes()) {
  97. return cell;
  98. }
  99. }
  100. return null; // If no empty cells are found
  101. }
  102. // Function to add the camera badge
  103. function addCameraBadge(userElement) {
  104. const videoBadge = document.createElement('div');
  105. videoBadge.classList.add('video-badge');
  106. const statusElement = userElement.querySelector('.status');
  107. if (statusElement) {
  108. statusElement.appendChild(videoBadge); // Append it to the user's status element
  109. }
  110. }
  111. // MutationObserver to monitor DOM for video-wrapper additions
  112. const observer = new MutationObserver(mutations => {
  113. mutations.forEach(mutation => {
  114. mutation.addedNodes.forEach(node => {
  115. if (node.nodeType === 1 && node.classList.contains('js-video') && !node.classList.contains('hidden')) {
  116. console.log("New video-wrapper detected:", node);
  117. // Modify the video element within the wrapper
  118. const videoElement = node.querySelector('video');
  119. if (videoElement) {
  120. console.log("Video element found:", videoElement);
  121. // Find an empty cell in the 5x5 grid and place the entire video wrapper
  122. const emptyCell = findEmptyCell();
  123. if (emptyCell) {
  124. console.log("Placing video wrapper in empty cell...");
  125. // Move the entire js-video element into the table cell
  126. emptyCell.appendChild(node);
  127. // Ensure the video takes up 100% of the cell's width and height
  128. videoElement.style.width = '100%';
  129. videoElement.style.height = '100%';
  130. // Adjust video wrapper styles if needed
  131. const videoWrapper = node.querySelector('.video-wrapper');
  132. if (videoWrapper) {
  133. videoWrapper.style.width = '100%';
  134. videoWrapper.style.height = '100%';
  135. }
  136. // Add camera badge if the user has their camera on
  137. const userElement = node.closest('.user-item'); // Replace with the correct selector for user elements
  138. const cameraStatus = userElement ? userElement.getAttribute('data-camera-status') : null; // Replace with the appropriate attribute or logic
  139. if (cameraStatus === 'active') { // Check if camera is active
  140. addCameraBadge(userElement);
  141. }
  142. }
  143. } else {
  144. console.warn("No video element found inside video-wrapper.");
  145. }
  146. }
  147. });
  148. });
  149. });
  150. // Start observing the DOM
  151. const targetNode = document.body;
  152. const config = { childList: true, subtree: true };
  153. observer.observe(targetNode, config);
  154. console.log("Observer initialized. Watching for js-video elements.");
  155. // Adding placeholder if needed (ensure vertical <br> appears in empty cells)
  156. function addPlaceholders() {
  157. const cells = table.getElementsByTagName("td");
  158. for (let cell of cells) {
  159. if (!cell.hasChildNodes()) {
  160. const placeholder = document.createElement('br');
  161. cell.appendChild(placeholder);
  162. }
  163. }
  164. }
  165. // Periodically check for empty cells and add placeholders
  166. setInterval(addPlaceholders, 1000);
  167. })();