📺 switching to Brunch

This commit is contained in:
Joshua Seigler 2017-09-12 12:02:31 -04:00
parent 9cd22b19b2
commit 7a3df002ee
20 changed files with 1337 additions and 1743 deletions

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="Layer_1" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 226.777 226.777" xml:space="preserve" height="226.78px" viewBox="0 0 226.777 226.777" width="226.78px" version="1.1" y="0px" x="0px" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata id="metadata9"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata><path id="path3" fill="#fff" opacity="0.2" d="m113.39 0c-62.623 0-113.39 50.767-113.39 113.39 0 62.62 50.766 113.39 113.39 113.39 62.62 0 113.39-50.77 113.39-113.39 0-62.623-50.77-113.39-113.39-113.39zm0 6.9668a106.42 106.42 0 0 1 106.42 106.42 106.42 106.42 0 0 1 -106.42 106.42 106.42 106.42 0 0 1 -106.42 -106.42 106.42 106.42 0 0 1 106.42 -106.42zm-35.624 69.328l-5.723 18.541h75.787l-11.41 37.114h-76.397l-5.72 18.54h81.227c7.94 0 10.06-1.39 15.74-4.71 5.67-3.33 10.1-9.14 12.5-16.06s8.26-26.44 10.06-32.947c1.8-6.506 2.49-8.998 0-13.839-2.49-4.847-7.61-6.639-11.49-6.639h-84.574zm-21.204 28.505l-5.236 17.03h45.264l5.24-17.03h-45.268z"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
app/assets/assets/bell.mp3 Normal file

Binary file not shown.

BIN
app/assets/assets/creek.mp3 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

17
app/assets/index.html Normal file
View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dash transaction visualizer</title>
<link rel="stylesheet" href="bundle.css">
</head>
<body>
<div id="muteToggle"></div>
<div id="connectionStatus" class="is-connecting"></div>
<div id="transactionList"></div>
<script src="https://blockchain.masternode.io/socket.io/socket.io.js"></script>
<script src="bundle.js"></script>
</body>
</html>

186
app/initialize.js Normal file
View file

@ -0,0 +1,186 @@
'use strict';
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
};
var domRefList = [];
window.addEventListener('load', init, false);
function init() {
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' : '');
}
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();
}
});
}
catch(e) {
console.error('Couldn\'t load sounds.');
}
socket.on('connect', function() {
document.getElementById('connectionStatus').className = 'is-connected';
// Join the room.
socket.emit('subscribe', 'inv');
})
socket.on('tx', onTransaction);
socket.on('block', onBlock);
socket.on('disconnect', function() {
document.getElementById('connectionStatus').className = 'is-disconnected';
});
socket.on('reconnecting', function() {
document.getElementById('connectionStatus').className = 'is-connecting';
});
}
function loadSound(url, bufferName, callback) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// 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();
}
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);
};
var onBlock = function(data) {
console.log(data);
playSound('block', 1);
var newBlock = document.createElement('a');
newBlock.className = 'blockDivider';
newBlock.href = 'https://blockchain.masternode.io/block/' + data;
newBlock.target = '_blank';
newBlock.setAttribute('rel', 'noopener');
newBlock.appendChild(document.createTextNode(data));
if (domRefList.unshift(newBlock) > 300) {
var toDelete = domRefList.pop();
toDelete.remove();
}
transactionList.insertBefore(newBlock, transactionList.firstChild);
};

158
app/styles/main.less Normal file
View file

@ -0,0 +1,158 @@
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);
}