asdf-games/node_modules/budo/lib/reload/client.js

156 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

var reloadCSS = require('reload-css')
var errorPopup = require('./error-popup')
module.exports = connect()
// EXPERIMENTAL: This feature may not last, use carefully.
// Attaches the API to 'budo-livereload' so you don't need to
// expose and require() it.
window['budo-livereload'] = module.exports
function connect () {
var reconnectPoll = 1000
var maxRetries = 50
var retries = 0
var reconnectInterval
var isReconnecting = false
var protocol = document.location.protocol
var hostname = document.location.hostname
var port = document.location.port
var host = hostname + ':' + port
var isIOS = /(iOS|iPhone|iPad|iPod)/i.test(navigator.userAgent)
var isSSL = /^https:/i.test(protocol)
var queued = []
var socket = createWebSocket()
var listeners = []
var api = {
send: function (message) {
message = JSON.stringify(message)
if (socket && socket.readyState === 1) {
socket.send(message)
} else {
queued.push(message)
}
},
listen: function (cb) {
if (typeof cb !== 'function') {
throw new TypeError('cb must be a function!')
}
listeners.push(cb)
},
removeListener: function (cb) {
var idx = listeners.indexOf(cb)
if (idx !== -1) {
listeners.splice(idx, 1)
}
},
showError: function (message) {
errorPopup.show(message)
},
clearError: function () {
errorPopup.hide()
},
reloadPage: reloadPage,
reloadCSS: reloadCSS
}
return api
function scheduleReconnect () {
if (isIOS && isSSL) {
// Special case for iOS with a self-signed certificate.
console.warn('[budo] LiveReload disconnected. You may need to generate and ' +
'trust a self-signed certificate, see here:\n' +
'https://github.com/mattdesl/budo/blob/master/docs/' +
'command-line-usage.md#ssl-on-ios')
return
}
if (isSSL) {
// Don't attempt to re-connect in SSL since it will likely be insecure
console.warn('[budo] LiveReload disconnected. Please reload the page to retry.')
return
}
if (retries >= maxRetries) {
console.warn('[budo] LiveReload disconnected, exceeded retry count. Please reload the page to retry.')
return
}
if (!isReconnecting) {
isReconnecting = true
console.warn('[budo] LiveReload disconnected, retrying...')
}
retries++
clearTimeout(reconnectInterval)
reconnectInterval = setTimeout(reconnect, reconnectPoll)
}
function reconnect () {
if (socket) {
// force close the existing socket
socket.onclose = function () {}
socket.close()
}
socket = createWebSocket()
}
function createWebSocket () {
var wsProtocol = isSSL ? 'wss://' : 'ws://'
var wsUrl = wsProtocol + host + '/livereload'
var ws = new window.WebSocket(wsUrl)
ws.onmessage = function (event) {
var data
try {
data = JSON.parse(event.data)
} catch (err) {
console.warn('Error parsing LiveReload server data: ' + event.data)
return
}
if (data.event === 'reload') {
if (/^\.?css$/i.test(data.ext)) {
reloadCSS(data.url)
} else {
reloadPage()
}
} else if (data.event === 'error-popup') {
if (data.message) errorPopup.show(data.message)
else errorPopup.hide()
}
// let listeners receive data
listeners.forEach(function (listener) {
listener(data)
})
}
ws.onclose = function (ev) {
if (ev.code === 1000 || ev.code === 1001) {
// Browser is navigating away.
return
}
scheduleReconnect()
}
ws.onopen = function () {
if (isReconnecting) {
isReconnecting = false
retries = 0
console.warn('[budo] LiveReload reconnected.')
}
if (queued.length && ws.readyState === 1) {
queued.forEach(function (message) {
ws.send(message)
})
queued.length = 0
}
}
ws.onerror = function () {
return false
}
return ws
}
}
function reloadPage () {
window.location.reload(true)
}