diff --git a/.common/utils/connection-status.css b/.common/utils/connection-status.css
new file mode 100644
index 0000000..b61bb89
--- /dev/null
+++ b/.common/utils/connection-status.css
@@ -0,0 +1,70 @@
+@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
+
+.connection-status {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ z-index: 99999;
+ font-family: 'Inter', sans-serif;
+ font-size: 30px;
+ font-weight: 700;
+ font-style: italic;
+ text-align: center;
+ color: white;
+
+ padding: 0.25em 1em;
+ border-radius: 10px;
+ background: #D12025;
+
+ box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.5);
+
+ /* Centering and entrance animation */
+ opacity: 0;
+ visibility: hidden;
+ transform: translate(-50%, calc(-50% + 10px));
+
+ transition:
+ opacity 200ms ease,
+ transform 200ms ease,
+ visibility 200ms ease;
+
+ pointer-events: none;
+ white-space: nowrap;
+}
+
+.connection-status.is-visible {
+ opacity: 0.9;
+ visibility: visible;
+ transform: translate(-50%, -50%);
+}
+
+/* Optional dark translucent backdrop */
+.connection-status-backdrop {
+ position: fixed;
+ inset: 0;
+ z-index: 99998;
+
+ background: rgba(0, 0, 0, 0.45);
+ opacity: 0;
+ visibility: hidden;
+
+ transition:
+ opacity 200ms ease,
+ visibility 200ms ease;
+
+ pointer-events: none;
+}
+
+.connection-status-backdrop.is-visible {
+ opacity: 1;
+ visibility: visible;
+}
+
+.connection-status--streamerbot {
+ background: linear-gradient(
+ 135deg,
+ #a257ed 0%,
+ #a257ed 20%,
+ #0b72ff 100%
+ );
+}
\ No newline at end of file
diff --git a/.common/utils/connection-status.js b/.common/utils/connection-status.js
new file mode 100644
index 0000000..f5bcae3
--- /dev/null
+++ b/.common/utils/connection-status.js
@@ -0,0 +1,76 @@
+
+class ConnectionStatus {
+ constructor({
+ target = document.body,
+ name = "Service",
+ disconnectedMessage,
+ className = "",
+ showDelay = 0,
+ } = {}) {
+ this.name = name;
+ this.showDelay = showDelay;
+ this.wasConnected = false;
+ this.disconnectTimer = null;
+
+ // Generate a CSS class from the service name.
+ const serviceClass = {
+ "Streamer.bot": "connection-status--streamerbot",
+ }[name] || "";
+
+ this.element = document.createElement("div");
+ this.element.className = [
+ "connection-status",
+ serviceClass,
+ className
+ ].filter(Boolean).join(" ");
+
+ this.element.setAttribute("role", "status");
+ this.element.setAttribute("aria-live", "polite");
+ this.element.hidden = true;
+
+ this.disconnectedMessage =
+ disconnectedMessage ?? `${name} disconnected`;
+
+ target.appendChild(this.element);
+ }
+
+ setConnected(connected) {
+ clearTimeout(this.disconnectTimer);
+ this.disconnectTimer = null;
+
+ if (connected) {
+ this.wasConnected = true;
+ this.hide();
+ return;
+ }
+
+ this.disconnectTimer = setTimeout(() => {
+ this.show(this.disconnectedMessage);
+ }, this.showDelay);
+ }
+
+ show(message) {
+ this.element.textContent = message;
+ this.element.hidden = false;
+ this.element.classList.remove("is-visible");
+
+ void this.element.offsetHeight;
+
+ this.element.classList.add("is-visible");
+ }
+
+ hide() {
+ this.element.classList.remove("is-visible");
+
+ setTimeout(() => {
+ if (!this.element.classList.contains("is-visible")) {
+ this.element.hidden = true;
+ }
+ }, 220);
+ }
+
+ destroy() {
+ clearTimeout(this.disconnectTimer);
+ this.element.remove();
+ }
+}
diff --git a/horizontal-chat/index.html b/horizontal-chat/index.html
index ccf2530..779bf35 100644
--- a/horizontal-chat/index.html
+++ b/horizontal-chat/index.html
@@ -8,7 +8,6 @@
- Connecting...
@@ -39,4 +38,6 @@
+
+
\ No newline at end of file
diff --git a/horizontal-chat/script.js b/horizontal-chat/script.js
index ed558fc..80eab63 100644
--- a/horizontal-chat/script.js
+++ b/horizontal-chat/script.js
@@ -125,6 +125,14 @@ document.documentElement.style.setProperty('--animation-speed', `${animationSpee
// STREAMER.BOT CLIENT //
/////////////////////////
+const connectionStatus = new ConnectionStatus({
+ name: "Streamer.bot",
+ showDelay: 1000,
+ disconnectedMessage: "Connecting to Streamer.bot..."
+});
+
+connectionStatus.setConnected(false);
+
const client = new StreamerbotClient({
host: sbServerAddress,
port: sbServerPort,
@@ -132,13 +140,13 @@ const client = new StreamerbotClient({
onConnect: (data) => {
console.log(`Streamer.bot successfully connected to ${sbServerAddress}:${sbServerPort}`)
console.debug(data);
- SetConnectionStatus(true);
+ connectionStatus.setConnected(true);
KickConnect();
},
onDisconnect: () => {
console.error(`Streamer.bot disconnected from ${sbServerAddress}:${sbServerPort}`)
- SetConnectionStatus(false);
+ connectionStatus.setConnected(false);
}
});
@@ -1848,30 +1856,4 @@ function GetWinnersList(gifts) {
const secondLastWinner = winners.pop();
return `${winners.join(", ")}, ${secondLastWinner} and ${lastWinner}`;
}
-}
-
-
-
-///////////////////////////////////
-// STREAMER.BOT WEBSOCKET STATUS //
-///////////////////////////////////
-
-// This function sets the visibility of the Streamer.bot status label on the overlay
-function SetConnectionStatus(connected) {
- let statusContainer = document.getElementById("statusContainer");
- if (connected) {
- statusContainer.style.background = "#2FB774";
- statusContainer.innerText = "Connected!";
- statusContainer.style.opacity = 1;
- setTimeout(() => {
- statusContainer.style.transition = "all 2s ease";
- statusContainer.style.opacity = 0;
- }, 10);
- }
- else {
- statusContainer.style.background = "#D12025";
- statusContainer.innerText = "Connecting...";
- statusContainer.style.transition = "";
- statusContainer.style.opacity = 1;
- }
}
\ No newline at end of file
diff --git a/horizontal-chat/style.css b/horizontal-chat/style.css
index 50553da..b879505 100644
--- a/horizontal-chat/style.css
+++ b/horizontal-chat/style.css
@@ -21,20 +21,6 @@ html {
overflow-wrap: break-word;
}
-#statusContainer {
- font-weight: 500;
- font-size: 30px;
- text-align: center;
- background-color: #D12025;
- color: white;
- padding: 10px;
- border-radius: 10px;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
-}
-
#mainContainer {
position: absolute;
height: calc(100% - 2 * var(--margin));
diff --git a/multichat-overlay/index.html b/multichat-overlay/index.html
index a5134d4..03f6542 100644
--- a/multichat-overlay/index.html
+++ b/multichat-overlay/index.html
@@ -9,7 +9,6 @@
-
@@ -106,4 +105,6 @@
+
+
\ No newline at end of file
diff --git a/multichat-overlay/script.js b/multichat-overlay/script.js
index e3f50a2..9f94784 100644
--- a/multichat-overlay/script.js
+++ b/multichat-overlay/script.js
@@ -145,6 +145,14 @@ document.documentElement.style.setProperty('--animation-speed', `${animationSpee
// STREAMER.BOT CLIENT //
/////////////////////////
+const connectionStatus = new ConnectionStatus({
+ name: "Streamer.bot",
+ showDelay: 1000,
+ disconnectedMessage: "Connecting to Streamer.bot..."
+});
+
+connectionStatus.setConnected(false);
+
const client = new StreamerbotClient({
host: sbServerAddress,
port: sbServerPort,
@@ -153,13 +161,13 @@ const client = new StreamerbotClient({
onConnect: (data) => {
console.log(`Streamer.bot successfully connected to ${sbServerAddress}:${sbServerPort}`)
console.debug(data);
- SetConnectionStatus(true);
+ connectionStatus.setConnected(true);
KickConnect();
},
onDisconnect: () => {
console.error(`Streamer.bot disconnected from ${sbServerAddress}:${sbServerPort}`)
- SetConnectionStatus(false);
+ connectionStatus.setConnected(false);
}
});
@@ -3383,32 +3391,6 @@ function GetWinnersList(gifts) {
}
}
-
-
-///////////////////////////////////
-// STREAMER.BOT WEBSOCKET STATUS //
-///////////////////////////////////
-
-// This function sets the visibility of the Streamer.bot status label on the overlay
-function SetConnectionStatus(connected) {
- let statusContainer = document.getElementById("statusContainer");
- if (connected) {
- statusContainer.style.background = "#2FB774";
- statusContainer.innerText = "Connected!";
- statusContainer.style.opacity = 1;
- setTimeout(() => {
- statusContainer.style.transition = "all 2s ease";
- statusContainer.style.opacity = 0;
- }, 10);
- }
- else {
- statusContainer.style.background = "#D12025";
- statusContainer.innerText = "Connecting...";
- statusContainer.style.transition = "";
- statusContainer.style.opacity = 1;
- }
-}
-
async function GetYouTubeVideoData(videoId) {
const url = `https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=${videoId}&format=json`;
diff --git a/multichat-overlay/style.css b/multichat-overlay/style.css
index 1e013c7..271b252 100644
--- a/multichat-overlay/style.css
+++ b/multichat-overlay/style.css
@@ -21,20 +21,6 @@ html {
overflow-wrap: break-word;
}
-#statusContainer {
- font-weight: 500;
- font-size: 30px;
- text-align: center;
- background-color: #D12025;
- color: white;
- padding: 10px;
- border-radius: 10px;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
-}
-
#mainContainer {
position: absolute;
height: calc(100% - 2 * var(--margin));
diff --git a/multistream-alerts/index.html b/multistream-alerts/index.html
index 6d1abb4..6d0688e 100644
--- a/multistream-alerts/index.html
+++ b/multistream-alerts/index.html
@@ -8,7 +8,6 @@
-
Connecting...
@@ -45,4 +44,6 @@
+
+
\ No newline at end of file
diff --git a/multistream-alerts/script.js b/multistream-alerts/script.js
index 6d3afe7..7b1c8b5 100644
--- a/multistream-alerts/script.js
+++ b/multistream-alerts/script.js
@@ -173,6 +173,14 @@ switch (alignment)
// STREAMER.BOT CLIENT //
/////////////////////////
+const connectionStatus = new ConnectionStatus({
+ name: "Streamer.bot",
+ showDelay: 1000,
+ disconnectedMessage: "Connecting to Streamer.bot..."
+});
+
+connectionStatus.setConnected(false);
+
const client = new StreamerbotClient({
host: sbServerAddress,
port: sbServerPort,
@@ -180,13 +188,13 @@ const client = new StreamerbotClient({
onConnect: (data) => {
console.log(`Streamer.bot successfully connected to ${sbServerAddress}:${sbServerPort}`)
console.debug(data);
- SetConnectionStatus(true);
+ connectionStatus.setConnected(true);
KickConnect();
},
onDisconnect: () => {
console.error(`Streamer.bot disconnected from ${sbServerAddress}:${sbServerPort}`)
- SetConnectionStatus(false);
+ connectionStatus.setConnected(false);
}
});
@@ -1813,29 +1821,4 @@ async function testWidget()
`O-oooooooooo AAAAE-A-A-I-A-U- JO-oooooooooooo AAE-O-A-A-U-U-A- E-eee-ee-eee AAAAE-A-E-I-E-A-JO-ooo-oo-oo-oo EEEEO-A-AAA-AAAA`
//``
);
-}
-
-
-///////////////////////////////////
-// STREAMER.BOT WEBSOCKET STATUS //
-///////////////////////////////////
-
-// This function sets the visibility of the Streamer.bot status label on the overlay
-function SetConnectionStatus(connected) {
- let statusContainer = document.getElementById("statusContainer");
- if (connected) {
- statusContainer.style.background = "#2FB774";
- statusContainer.innerText = "Connected!";
- statusContainer.style.opacity = 1;
- setTimeout(() => {
- statusContainer.style.transition = "all 2s ease";
- statusContainer.style.opacity = 0;
- }, 10);
- }
- else {
- statusContainer.style.background = "#D12025";
- statusContainer.innerText = "Connecting...";
- statusContainer.style.transition = "";
- statusContainer.style.opacity = 1;
- }
}
\ No newline at end of file
diff --git a/multistream-alerts/style.css b/multistream-alerts/style.css
index 58a1cd1..c310dc8 100644
--- a/multistream-alerts/style.css
+++ b/multistream-alerts/style.css
@@ -22,20 +22,6 @@ html {
overflow-wrap: break-word;
}
-#statusContainer {
- font-weight: 500;
- font-size: 30px;
- text-align: center;
- background-color: #D12025;
- color: white;
- padding: 10px;
- border-radius: 10px;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
-}
-
#mainContainer {
position: absolute;
width: 100%;
diff --git a/now-playing/themes/color-palette/script.js b/now-playing/themes/color-palette/script.js
index bb194e4..b0a0a2d 100644
--- a/now-playing/themes/color-palette/script.js
+++ b/now-playing/themes/color-palette/script.js
@@ -91,6 +91,8 @@ async function ChangeTrack(mediaProps, accentColorPalette) {
boxes[role].style.color = colorValue;
labels[role].style.opacity = '';
});
+
+ SetVisibility(true); // Show the overlay for a few seconds if autoHide is enabled
}, 250);
}
diff --git a/obs-info-hud/index.html b/obs-info-hud/index.html
index afcb382..f33560c 100644
--- a/obs-info-hud/index.html
+++ b/obs-info-hud/index.html
@@ -8,7 +8,6 @@
-
Connecting...
@@ -77,4 +76,6 @@
+
+
\ No newline at end of file
diff --git a/obs-info-hud/script.js b/obs-info-hud/script.js
index 0e95aa5..0773a32 100644
--- a/obs-info-hud/script.js
+++ b/obs-info-hud/script.js
@@ -25,6 +25,13 @@ let previousOutputTimecode = 0;
let previousOutputBytes = 0;
let activeFps;
+const connectionStatus = new ConnectionStatus({
+ showDelay: 1000,
+ disconnectedMessage: "Connecting to Streamer.bot..."
+});
+
+connectionStatus.setConnected(false);
+
function connectws() {
if ("WebSocket" in window) {
@@ -32,7 +39,7 @@ function connectws() {
// Reconnect
ws.onclose = function () {
- SetConnectionStatus(false);
+ connectionStatus.setConnected(false);
setTimeout(connectws, 5000);
};
@@ -67,7 +74,7 @@ function connectws() {
break;
case 2: // Identify OpCode
console.log("Connected to OBS!");
- SetConnectionStatus(true);
+ connectionStatus.setConnected(true);
break;
case 5: // Event OpCode
switch (data.d.eventType) {
@@ -379,26 +386,6 @@ function hexToBase64(hexstring) {
// WEBSOCKET STATUS //
//////////////////////
-// This function sets the visibility of the Streamer.bot status label on the overlay
-function SetConnectionStatus(connected) {
- let statusContainer = document.getElementById("statusContainer");
-
- if (connected) {
- statusContainer.style.background = "#2FB774";
- statusContainer.innerText = "Connected!";
- mainContainer.style.visibility = `visible`;
- var tl = new TimelineMax();
- tl
- .to(statusContainer, 2, { opacity: 0, ease: Linear.easeNone });
- }
- else {
- statusContainer.style.background = "#D12025";
- statusContainer.innerText = "Connecting...";
- statusContainer.style.opacity = 1;
- mainContainer.style.visibility = `hidden`;
- }
-}
-
connectws();
setInterval(GetStreamStatus, 1000);
diff --git a/obs-info-hud/style.css b/obs-info-hud/style.css
index 2effbd0..2a1f8d5 100644
--- a/obs-info-hud/style.css
+++ b/obs-info-hud/style.css
@@ -6,24 +6,6 @@ body {
background-size: cover;
}
-#statusContainer {
- font-family: 'Metropolis';
- font-style: italic;
- font-weight: bold;
- font-size: 30px;
- width: 400px;
- max-width: fit-content;
- text-align: center;
- background-color: #D12025;
- color: white;
- padding: 10px;
- border-radius: 10px;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
-}
-
#top,
#bottom,
#left,
diff --git a/twitch-ad-countdown-timer/index.html b/twitch-ad-countdown-timer/index.html
index 71d8c37..fc5f623 100644
--- a/twitch-ad-countdown-timer/index.html
+++ b/twitch-ad-countdown-timer/index.html
@@ -9,7 +9,6 @@
-
Connecting...
@@ -26,4 +25,6 @@
+
+
\ No newline at end of file
diff --git a/twitch-ad-countdown-timer/script.js b/twitch-ad-countdown-timer/script.js
index bae7b05..b4c7ef8 100644
--- a/twitch-ad-countdown-timer/script.js
+++ b/twitch-ad-countdown-timer/script.js
@@ -113,6 +113,14 @@ switch (timerPosition) {
// STREAMER.BOT CLIENT //
/////////////////////////
+const connectionStatus = new ConnectionStatus({
+ name: "Streamer.bot",
+ showDelay: 1000,
+ disconnectedMessage: "Connecting to Streamer.bot..."
+});
+
+connectionStatus.setConnected(false);
+
const client = new StreamerbotClient({
host: sbServerAddress,
port: sbServerPort,
@@ -120,12 +128,12 @@ const client = new StreamerbotClient({
onConnect: (data) => {
console.log(`Streamer.bot successfully connected to ${sbServerAddress}:${sbServerPort}`)
console.debug(data);
- SetConnectionStatus(true);
+ connectionStatus.setConnected(true);
},
onDisconnect: () => {
console.error(`Streamer.bot disconnected from ${sbServerAddress}:${sbServerPort}`)
- SetConnectionStatus(false);
+ connectionStatus.setConnected(false);
}
});
@@ -355,31 +363,4 @@ function testAd() {
function testUpcomingAdWarning() {
UpcomingAdWarning(warningSeconds);
-}
-
-
-
-
-///////////////////////////////////
-// STREAMER.BOT WEBSOCKET STATUS //
-///////////////////////////////////
-
-// This function sets the visibility of the Streamer.bot status label on the overlay
-function SetConnectionStatus(connected) {
- let statusContainer = document.getElementById("statusContainer");
- if (connected) {
- statusContainer.style.background = "#2FB774";
- statusContainer.innerText = "Connected!";
- statusContainer.style.opacity = 1;
- setTimeout(() => {
- statusContainer.style.transition = "all 2s ease";
- statusContainer.style.opacity = 0;
- }, 10);
- }
- else {
- statusContainer.style.background = "#D12025";
- statusContainer.innerText = "Connecting...";
- statusContainer.style.transition = "";
- statusContainer.style.opacity = 1;
- }
}
\ No newline at end of file
diff --git a/twitch-ad-countdown-timer/style.css b/twitch-ad-countdown-timer/style.css
index 6033fd4..411ce46 100644
--- a/twitch-ad-countdown-timer/style.css
+++ b/twitch-ad-countdown-timer/style.css
@@ -14,20 +14,6 @@ html {
overflow-wrap: break-word; */
}
-#statusContainer {
- font-weight: 500;
- font-size: 30px;
- text-align: center;
- background-color: #D12025;
- color: white;
- padding: 10px;
- border-radius: 10px;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
-}
-
#timer-bar {
width: 0px;
height: 0px;