From 34dabd963c0adfb5eff16444578335d0cc26a44d Mon Sep 17 00:00:00 2001 From: Joshua Seigler Date: Thu, 4 Apr 2019 03:52:56 -0400 Subject: [PATCH] Visualize Dash blocks as Jackson Polluck style paintings --- app/application.js | 248 +++++++++--------------- app/assets/assets/paint/paint-big01.svg | 2 +- app/assets/assets/paint/paint-big02.svg | 2 +- app/assets/assets/paint/paint-big03.svg | 2 +- app/assets/assets/paint/paint-big04.svg | 2 +- app/assets/assets/paint/paint-big05.svg | 2 +- app/assets/assets/paint/paint-big06.svg | 2 +- app/assets/assets/paint/paint-big07.svg | 2 +- app/assets/assets/paint/paint-big08.svg | 2 +- app/assets/assets/paint/paint-big09.svg | 2 +- app/assets/assets/paint/paint-big10.svg | 2 +- app/assets/assets/paint/paint-big11.svg | 2 +- app/assets/assets/paint/paint-big12.svg | 2 +- app/assets/assets/paint/paint01.svg | 2 +- app/assets/assets/paint/paint02.svg | 2 +- app/assets/assets/paint/paint03.svg | 2 +- app/assets/assets/paint/paint04.svg | 2 +- app/assets/assets/paint/paint05.svg | 2 +- app/assets/assets/paint/paint06.svg | 2 +- app/assets/assets/paint/paint07.svg | 2 +- app/assets/assets/paint/paint08.svg | 2 +- app/assets/assets/paint/paint09.svg | 2 +- app/assets/assets/paint/paint10.svg | 2 +- app/assets/assets/paint/paint11.svg | 2 +- app/assets/index.html | 3 +- app/styles/main.css | 121 ++++++++++++ app/styles/main.less | 158 --------------- 27 files changed, 242 insertions(+), 334 deletions(-) create mode 100644 app/styles/main.css delete mode 100644 app/styles/main.less diff --git a/app/application.js b/app/application.js index e781a84..0250120 100644 --- a/app/application.js +++ b/app/application.js @@ -4,172 +4,118 @@ const io = require('socket.io-client'); var App = { init: function init() { - var socket = io("https://insight.dash.org:443/"); - var transactionList = document.getElementById('transactionList'); - var muteButton = document.getElementById('muteToggle'); - var muted = false; - var audioContext; - var audioGainNode; - var backgroundSound; - var soundBuffers = { - 'tx': null, - 'block': null - }; + const socket = io("https://insight.dash.org:443/"); + const blockList = document.getElementById('blockList'); var domRefList = []; + var currentBlock = document.createElement('div'); + currentBlock.className = 'block'; + blockList.appendChild(currentBlock); - function loadSound(url, bufferName, callback) { - var request = new XMLHttpRequest(); - request.open('GET', url, true); - request.responseType = 'arraybuffer'; + const psInputSatoshis = [ + 1000010000, + 100001000, + 10000100, + 1000010, + 100001 + ]; - // Decode asynchronously - request.onload = function() { - audioContext.decodeAudioData(request.response, function(buffer) { - soundBuffers[bufferName] = buffer; - if (callback) { - callback(); - } - }); - console.log('Loaded ' + url + ' as "' + bufferName + '"'); - } - request.send(); - } + const COLORS = { + private: 'black', + instant: 'white' + }; - function playSound(bufferName, playbackRate) { - if (muted === true) { - return; - } - var source = audioContext.createBufferSource(); - source.buffer = soundBuffers[bufferName]; - source.connect(audioGainNode); - source.playbackRate.value = playbackRate; - source.start(); - } - - function playbackRate(value, vMin, vMax, oMin, oMax) { - return Math.min(Math.max(oMin, - (Math.log(value) - Math.log(vMin)) / (Math.log(vMax) - Math.log(vMin)) * (oMin - oMax) + oMax - ), oMax); - } - - var toggleMute = function() { - muted = !muted; - if (localStorage) { - localStorage.setItem('muted', muted); - } - muteButton.className = (muted === true ? 'is-muted' : ''); - if (muted) { - backgroundSound.stop(); - } else { - backgroundSound = audioContext.createBufferSource(); - backgroundSound.buffer = soundBuffers['background']; - backgroundSound.connect(audioGainNode); - backgroundSound.loop = true; - backgroundSound.start(); - } - } - - var onTransaction = function(data) { - console.log(data); - if (!muted) { - if (data.valueOut < 10) { - playSound('tx-sm', playbackRate(data.valueOut, 0.00001, 10, 1, 1.5)); - } else if (data.valueOut < 1000) { - playSound('tx-md', playbackRate(data.valueOut, 10, 1000, 0.5, 1)); - } else if (data.valueOut >= 1000) { - playSound('tx-lg', playbackRate(data.valueOut, 6000, 1000, 0.25, 1)); - } - } - var tx = document.createElement('div'); - tx.className = 'tx'; - var txValue = document.createElement('a'); - txValue.className = 'txValue'; - txValue.href = 'https://blockchain.masternode.io/tx/' + data.txid; - txValue.target = '_blank'; - txValue.setAttribute('rel', 'noopener'); - var txOutputs = document.createElement('div'); - txOutputs.className = 'txOutputs'; - txOutputs.style.height = (data.valueOut / 10 + 0.1) + 'em' - txValue.appendChild(document.createTextNode(data.valueOut)); - tx.appendChild(txValue); - tx.appendChild(txOutputs); - var transactions = data.vout; - // var transactions = data.vout.sort(function(a, b) { // sort descending by tx value - // return b[Object.keys(b)[0]] - a[Object.keys(a)[0]]; - // }); - transactions.forEach(function(value, index, array) { - var txOut = document.createElement('div'); - var outputSatoshis = value[Object.keys(value)[0]]; - txOut.className = 'txOut'; - txOut.style.width = (outputSatoshis * 0.00001).toFixed(4) + 'px'; - txOut.title = (value[Object.keys(value)[0]] * 0.00000001); - txOutputs.appendChild(txOut); - }); - if (domRefList.unshift(tx) > 300) { - var toDelete = domRefList.pop(); - toDelete.remove(); - } - transactionList.insertBefore(tx, transactionList.firstChild); + const PAINT = { + big: [ + 'paint-big01.svg', + 'paint-big02.svg', + 'paint-big03.svg', + 'paint-big04.svg', + 'paint-big05.svg', + 'paint-big06.svg', + 'paint-big07.svg', + 'paint-big08.svg', + 'paint-big09.svg', + 'paint-big00.svg', + 'paint-big01.svg', + 'paint-big11.svg', + 'paint-big12.svg' + ], + small: [ + 'paint01.svg', + 'paint02.svg', + 'paint03.svg', + 'paint04.svg', + 'paint05.svg', + 'paint06.svg', + 'paint07.svg', + 'paint08.svg', + 'paint09.svg', + 'paint00.svg', + 'paint01.svg', + 'paint11.svg' + ] }; var onBlock = function(data) { console.log(data); - playSound('block', 1); - var newBlock = document.createElement('a'); - newBlock.className = 'blockDivider'; - newBlock.href = 'https://insight.dash.org/insight/block/' + data; - newBlock.target = '_blank'; - newBlock.setAttribute('rel', 'noopener'); - newBlock.appendChild(document.createTextNode(data)); - if (domRefList.unshift(newBlock) > 300) { + var blockLink = document.createElement('a'); + blockLink.className = 'explorer-link'; + blockLink.href = 'https://insight.dash.org/insight/block/' + data; + blockLink.target = '_blank'; + blockLink.setAttribute('rel', 'noopener'); + blockLink.appendChild(document.createTextNode(data)); + currentBlock.appendChild(blockLink); + + currentBlock = document.createElement('div'); + currentBlock.className = 'block'; + currentBlock.style.setProperty('--private-color', COLORS.private); + currentBlock.style.setProperty('--instant-color', COLORS.instant); + currentBlock.style.setProperty('--default-color', COLORS.default); + + if (domRefList.unshift(currentBlock) > 16) { var toDelete = domRefList.pop(); toDelete.remove(); } - transactionList.insertBefore(newBlock, transactionList.firstChild); + blockList.insertBefore(currentBlock, blockList.firstChild); }; - if (localStorage) { - muted = localStorage.getItem('muted'); - if (muted === null) { - muted = false; - localStorage.setItem('muted', muted); - } else { - muted = (muted == 'true'); // localStorage stores strings not objects? - } - muteButton.className = (muted === true ? 'is-muted' : ''); - } + const onTransaction = function(data) { + var transactions = data.vout; - muteButton.onclick = toggleMute; - - try { - window.AudioContext = window.AudioContext||window.webkitAudioContext; - audioContext = new AudioContext(); - audioGainNode = audioContext.createGain(); - audioGainNode.connect(audioContext.destination); - audioGainNode.gain.value = 0.6; - } - catch(e) { - console.error('Unable to use Web Audio API'); - document.getElementById('muteToggle').remove(); - } - try { - loadSound('assets/whoosh.mp3', 'block'); - loadSound('assets/bell.mp3', 'tx-sm'); - loadSound('assets/wood-hit-glass.mp3', 'tx-md'); - loadSound('assets/metallophone.mp3', 'tx-lg'); - loadSound('assets/creek.mp3', 'background', function() { - backgroundSound = audioContext.createBufferSource(); - backgroundSound.buffer = soundBuffers['background']; - backgroundSound.connect(audioGainNode); - backgroundSound.loop = true; - if (!muted) { - backgroundSound.start(); + var isPrivateSend = true; + for (let i = 0; i < transactions.length; i++) { + const tx = transactions[i]; + const outputSatoshis = tx[Object.keys(tx)[0]]; + if (!psInputSatoshis.includes(outputSatoshis)) { + isPrivateSend = false; + break; } - }); - } - catch(e) { - console.error('Couldn\'t load sounds.'); - } + } + + const tx = { + private: isPrivateSend, + instant: data.txlock, + value: data.valueOut, + x: parseInt(data.txid.slice(0, 4), 16) / 65536, + y: parseInt(data.txid.slice(4, 8), 16) / 65536, + rotation: parseInt(data.txid.slice(16, 17), 16) / 16, + paintIndex: parseInt(data.txid.slice(17, 21), 16) / 65536, + color: isPrivateSend ? COLORS.private : data.txlock ? COLORS.instant : '#' + data.txid.slice(21, 27) + }; + + var paint = document.createElement('div'); + paint.classList.add('paint'); + paint.style.backgroundImage = 'linear-gradient(0deg,'+tx.color+','+tx.color+')'; + paint.style.maskImage = 'url(assets/paint/' + (tx.value > 10 ? + PAINT.big[Math.floor(tx.paintIndex * 12)] : + PAINT.small[Math.floor(tx.paintIndex * 11)] + ) + ')'; + paint.style.setProperty('--x', tx.x); + paint.style.setProperty('--y', tx.y); + paint.style.setProperty('--size', Math.log(1 + tx.value)/Math.log(2)); + paint.style.setProperty('--rotation', tx.rotation * 360 + 'deg'); + currentBlock.appendChild(paint, currentBlock.firstChild); + }; socket.on('connect', function() { document.getElementById('connectionStatus').className = 'is-connected'; diff --git a/app/assets/assets/paint/paint-big01.svg b/app/assets/assets/paint/paint-big01.svg index 66a48e6..fc2c648 100644 --- a/app/assets/assets/paint/paint-big01.svg +++ b/app/assets/assets/paint/paint-big01.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint-big02.svg b/app/assets/assets/paint/paint-big02.svg index 96c3fdf..96e3bf5 100644 --- a/app/assets/assets/paint/paint-big02.svg +++ b/app/assets/assets/paint/paint-big02.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint-big03.svg b/app/assets/assets/paint/paint-big03.svg index e4df362..1500bff 100644 --- a/app/assets/assets/paint/paint-big03.svg +++ b/app/assets/assets/paint/paint-big03.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint-big04.svg b/app/assets/assets/paint/paint-big04.svg index e62dfe5..d02b2a0 100644 --- a/app/assets/assets/paint/paint-big04.svg +++ b/app/assets/assets/paint/paint-big04.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint-big05.svg b/app/assets/assets/paint/paint-big05.svg index 3c48721..d09a716 100644 --- a/app/assets/assets/paint/paint-big05.svg +++ b/app/assets/assets/paint/paint-big05.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint-big06.svg b/app/assets/assets/paint/paint-big06.svg index bcc6d84..ea5dd4a 100644 --- a/app/assets/assets/paint/paint-big06.svg +++ b/app/assets/assets/paint/paint-big06.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint-big07.svg b/app/assets/assets/paint/paint-big07.svg index 02d2961..65a7f94 100644 --- a/app/assets/assets/paint/paint-big07.svg +++ b/app/assets/assets/paint/paint-big07.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint-big08.svg b/app/assets/assets/paint/paint-big08.svg index 789993a..3f85f3d 100644 --- a/app/assets/assets/paint/paint-big08.svg +++ b/app/assets/assets/paint/paint-big08.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint-big09.svg b/app/assets/assets/paint/paint-big09.svg index 37abd68..baf11b5 100644 --- a/app/assets/assets/paint/paint-big09.svg +++ b/app/assets/assets/paint/paint-big09.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint-big10.svg b/app/assets/assets/paint/paint-big10.svg index 31e73fb..54f28cf 100644 --- a/app/assets/assets/paint/paint-big10.svg +++ b/app/assets/assets/paint/paint-big10.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint-big11.svg b/app/assets/assets/paint/paint-big11.svg index e2c65a4..984e0d4 100644 --- a/app/assets/assets/paint/paint-big11.svg +++ b/app/assets/assets/paint/paint-big11.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint-big12.svg b/app/assets/assets/paint/paint-big12.svg index b4b4ceb..71c8df6 100644 --- a/app/assets/assets/paint/paint-big12.svg +++ b/app/assets/assets/paint/paint-big12.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint01.svg b/app/assets/assets/paint/paint01.svg index f16cbe1..1617e9c 100644 --- a/app/assets/assets/paint/paint01.svg +++ b/app/assets/assets/paint/paint01.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint02.svg b/app/assets/assets/paint/paint02.svg index bc14044..44886ce 100644 --- a/app/assets/assets/paint/paint02.svg +++ b/app/assets/assets/paint/paint02.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint03.svg b/app/assets/assets/paint/paint03.svg index 0e15e77..e8752e6 100644 --- a/app/assets/assets/paint/paint03.svg +++ b/app/assets/assets/paint/paint03.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint04.svg b/app/assets/assets/paint/paint04.svg index 5fa2af0..d9b9fd5 100644 --- a/app/assets/assets/paint/paint04.svg +++ b/app/assets/assets/paint/paint04.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint05.svg b/app/assets/assets/paint/paint05.svg index 7cf19cd..ee3b560 100644 --- a/app/assets/assets/paint/paint05.svg +++ b/app/assets/assets/paint/paint05.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint06.svg b/app/assets/assets/paint/paint06.svg index 75bf7c8..cf483d9 100644 --- a/app/assets/assets/paint/paint06.svg +++ b/app/assets/assets/paint/paint06.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint07.svg b/app/assets/assets/paint/paint07.svg index 890bc57..dfe8959 100644 --- a/app/assets/assets/paint/paint07.svg +++ b/app/assets/assets/paint/paint07.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint08.svg b/app/assets/assets/paint/paint08.svg index 02429a1..040e797 100644 --- a/app/assets/assets/paint/paint08.svg +++ b/app/assets/assets/paint/paint08.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint09.svg b/app/assets/assets/paint/paint09.svg index 977a348..c47b8c1 100644 --- a/app/assets/assets/paint/paint09.svg +++ b/app/assets/assets/paint/paint09.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint10.svg b/app/assets/assets/paint/paint10.svg index 9ac1be4..99633a3 100644 --- a/app/assets/assets/paint/paint10.svg +++ b/app/assets/assets/paint/paint10.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/assets/paint/paint11.svg b/app/assets/assets/paint/paint11.svg index f666bef..75b22b2 100644 --- a/app/assets/assets/paint/paint11.svg +++ b/app/assets/assets/paint/paint11.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/index.html b/app/assets/index.html index 814e393..a0a9d0b 100644 --- a/app/assets/index.html +++ b/app/assets/index.html @@ -6,10 +6,9 @@ -
-
+
diff --git a/app/styles/main.css b/app/styles/main.css new file mode 100644 index 0000000..2e21068 --- /dev/null +++ b/app/styles/main.css @@ -0,0 +1,121 @@ +body { + padding: 0; + margin: 0; + box-sizing: border-box; + font-family: sans-serif; + font-size: 140%; + background-image: url('assets/Dash-logo.svg'); + background-size: 50vmin auto, cover; + background-position: center; + background-attachment: fixed; + background-repeat: no-repeat; + background-color: #bbb; + color: black; + height: 100vh; + overflow: hidden; +} +* { + box-sizing: inherit; +} +a { + color: inherit; + text-decoration: none; +} +#connectionStatus.is-connected ~ #transactionList:empty:before { + content: 'Waiting for first transaction...'; + display: block; + text-align: center; + font-size: 2em; + opacity: 0.5; +} +#blockList { + margin-left: 80vw; + padding-top: 2.5vw; +} +.block:first-child { + position: absolute; + left: 41.125%; + top: 50%; + width: 77.5vw; + height: 77.5vw; + transform: translate(-50%,-50%); +} +@media (max-height: 77.5vw) { + .block:first-child { + width: calc(100vh - 5vw); + height: calc(100vh - 5vw); + } +} +.block { + width: 15vw; + height: 15vw; + box-shadow: 0.1em 0.1em 1em hsla(0, 0%, 0%, 0.5); + background-color: #eee; + margin: 0 auto 1em; + position: relative; + overflow: hidden; +} +.explorer-link { + display: none; + position: absolute; + z-index: 1; + font-size: 1.9vmin; + text-align: center; + background-color: hsla(0, 0%, 100%, 0.5); + color: transparent; + height: 100%; + width: 100%; +} +.block:hover .explorer-link { + display: block; +} +.paint { + position: absolute; + left: calc(var(--x) * 90% + 5%); + top: calc(var(--y) * 90% + 5%); + transform: translate(-50%, -50%) rotate(var(--rotation)); + height: calc(var(--size) * 20% + 20%); + width: calc(var(--size) * 20% + 20%); + mask-size: contain; + mask-repeat: no-repeat; + mask-position: center; +} + +#muteToggle, #connectionStatus { + position: fixed; + top: 0; + width: 8em; + background: white; + border: solid black; + padding: 0.5em; + font-size: 0.8em; + text-transform: uppercase; + font-weight: bold; + text-align: center; + color: black; +} + +#connectionStatus { + right: 0; + border-radius: 0 0 0 0.5em; + border-width: 0 0 0.1em 0.1em; + transition: transform 0.5s; + transform: none; +} +#connectionStatus.is-disconnected:before { + content: 'Disconnected'; + color: red; +} +#connectionStatus.is-connecting:before { + content: 'Connecting...'; + color: black; +} +#connectionStatus.is-connected:before { + content: 'Connected'; + color: green; +} +#connectionStatus.is-connected { + transition: transform 0.5s; + transition-delay: 2s; + transform: translate3d(0, -100%, 0); +} diff --git a/app/styles/main.less b/app/styles/main.less deleted file mode 100644 index 5505ab1..0000000 --- a/app/styles/main.less +++ /dev/null @@ -1,158 +0,0 @@ -body { - padding: 0; - margin: 0; - box-sizing: border-box; - font-family: sans-serif; - font-size: 140%; - background-image: url('assets/Dash-logo.svg'), linear-gradient(to bottom right, hsl(208, 73%, 43%), hsl(208, 86.5%, 21.5%)); - background-size: 50vmin auto, cover; - background-position: center; - background-attachment: fixed; - background-repeat: no-repeat; - background-color: hsl(208, 73%, 43%); - color: white; - min-height: 100vh; -} -* { - box-sizing: inherit; -} -a { - color: inherit; - text-decoration: none; -} -#transactionList { - padding: 1em 0 0; - mix-blend-mode: screen; - opacity: 0.75; - height: 100vh; - overflow: hidden; -} -#transactionList:after { - content: ''; - position: fixed; - bottom: 0; - height: 8em; - left: 0; - right: 0; - background-image: linear-gradient(to top, black, transparent); - z-index: 2; - pointer-events: none; -} -#connectionStatus.is-connected ~ #transactionList:empty:before { - content: 'Waiting for first transaction...'; - display: block; - text-align: center; - font-size: 2em; - opacity: 0.5; -} -.tx { - position: relative; - margin: 3px auto; - width: 20em; - min-width: 80%; - max-width: 100%; - z-index: 1; -} -.txValue { - display: none; - flex: 0 0 auto; - line-height: 1.25; -} -.txOutputs { - display: flex; - flex-wrap: nowrap; - flex-direction: row; - align-content: stretch; -} -.txOut { - position: relative; - flex: 1 1 auto; - background-color: white; -} -.txOut:first { - border-left: 3px solid black; -} -.txOut:after { - content: ''; - width: 3px; - background: black; - position: absolute; - right: 0; - top: 0; - bottom: 0; -} - -.blockDivider { - display: block; - margin: 1em -1em -1.5em; - background: linear-gradient(to top, rgba(255,255,255,0), rgba(255,255,255,0.125)); - padding: 0.125em 1em 1.5em; - color: rgba(0,0,0,0); - text-align: center; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} -.blockDivider:hover, .blockDivider:focus { - color: inherit; -} - -#muteToggle, #connectionStatus { - position: fixed; - top: 0; - width: 8em; - background: white; - border: solid black; - padding: 0.5em; - font-size: 0.8em; - text-transform: uppercase; - font-weight: bold; - text-align: center; - color: black; -} - -#muteToggle { - left: 0; - border-radius: 0 0 0.5em 0; - border-width: 0 0.1em 0.1em 0; - transition: opacity 0.5s; - transition-delay: 1s; - opacity: 0; - cursor: pointer; - z-index: 100; -} -#muteToggle:hover { - opacity: 1; - transition-delay: 0s; -} -#muteToggle:before { - content: 'Mute'; -} -#muteToggle.is-muted:before { - content: 'Un-mute'; -} - -#connectionStatus { - right: 0; - border-radius: 0 0 0 0.5em; - border-width: 0 0 0.1em 0.1em; - transition: transform 0.5s; - transform: none; -} -#connectionStatus.is-disconnected:before { - content: 'Disconnected'; - color: red; -} -#connectionStatus.is-connecting:before { - content: 'Connecting...'; - color: black; -} -#connectionStatus.is-connected:before { - content: 'Connected'; - color: green; -} -#connectionStatus.is-connected { - transition: transform 0.5s; - transition-delay: 2s; - transform: translate3d(0, -100%, 0); -}