From 2b4b364d0da457c87817db8d0e9f6acfea2dd410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 16 Sep 2017 01:14:43 +0200 Subject: [PATCH] improved loader and reconnect behavior --- js/appcommon.js | 16 +++++++++++++- js/term.js | 12 +++++------ js/term_conn.js | 50 +++++++++++++++++++++++++++++++------------ js/term_screen.js | 14 +++++++++--- sass/pages/_term.scss | 7 ++++++ 5 files changed, 75 insertions(+), 24 deletions(-) diff --git a/js/appcommon.js b/js/appcommon.js index f1c4c6a..4b6cc83 100644 --- a/js/appcommon.js +++ b/js/appcommon.js @@ -116,14 +116,28 @@ $._loader = function (vis) { $('#loader').toggleClass('show', vis) } +let pageShown = false // reveal content on load function showPage () { + pageShown = true $('#content').addClass('load') } // Auto reveal pages other than the terminal (sets window.noAutoShow) $.ready(function () { - if (window.noAutoShow !== true) { + if (window.noAutoShow === true) { + setTimeout(function () { + if (!pageShown) { + let bnr = mk('P') + bnr.id = 'load-failed' + bnr.innerHTML = + 'Server connection failed! Trying again' + + '.' + qs('#screen').appendChild(bnr) + showPage() + } + }, 2000) + } else { setTimeout(function () { showPage() }, 1) diff --git a/js/term.js b/js/term.js index 0d9ccae..6847be5 100644 --- a/js/term.js +++ b/js/term.js @@ -6,12 +6,12 @@ window.termInit = function ({ labels, theme, allFn }) { const termUpload = TermUpl(conn, input, screen) screen.input = input - conn.on('open', () => { screen.window.statusScreen = null }) - conn.on('connect', () => { screen.window.statusScreen = { title: 'Connecting', loading: true } }) - conn.on('close', () => { screen.window.statusScreen = { title: 'Disconnected' } }) - conn.on('ping', () => { screen.window.statusScreen = { title: 'Disconnected', loading: true } }) - conn.on('ping-fail', () => { screen.window.statusScreen = { title: 'Disconnected' } }) - conn.on('ping-success', () => { screen.window.statusScreen = { title: 'Reloading', loading: true } }) + conn.on('open', () => { screen.window.statusScreen = { title: 'Connecting', loading: true } }) + conn.on('connect', () => { screen.window.statusScreen = null }) + conn.on('disconnect', () => { screen.window.statusScreen = { title: 'Disconnected' } }) + conn.on('silence', () => { screen.window.statusScreen = { title: 'Waiting for server', loading: true } }) + // conn.on('ping-fail', () => { screen.window.statusScreen = { title: 'Disconnected' } }) + conn.on('ping-success', () => { screen.window.statusScreen = { title: 'Re-connecting', loading: true } }) conn.init() input.init({ allFn }) diff --git a/js/term_conn.js b/js/term_conn.js index d5c3ba7..efff328 100644 --- a/js/term_conn.js +++ b/js/term_conn.js @@ -9,7 +9,8 @@ window.Conn = class TermConnection extends EventEmitter { this.pingInterval = null this.xoff = false this.autoXoffTimeout = null - this.reconTimeout = null + this.reconnTimeout = null + this.forceClosing = false this.pageShown = false } @@ -19,22 +20,26 @@ window.Conn = class TermConnection extends EventEmitter { this.heartbeat() this.send('i') - this.emit('open') + this.emit('connect') } onWSClose (evt) { + if (this.forceClosing) return console.warn('SOCKET CLOSED, code ' + evt.code + '. Reconnecting...') - clearTimeout(this.reconTimeout) - this.reconTimeout = setTimeout(() => this.init(), 2000) - // this happens when the buffer gets fucked up via invalid unicode. - // we basically use polling instead of socket then + if (evt.code < 1000) { + console.error('Bad code from socket!') + // this sometimes happens for unknown reasons, code < 1000 is invalid + location.reload() + } - this.emit('close', evt.code) + clearTimeout(this.reconnTimeout) + this.reconnTimeout = setTimeout(() => this.init(), 2000) + + this.emit('disconnect', evt.code) } onWSMessage (evt) { try { - // . = heartbeat switch (evt.data.charAt(0)) { case '.': // heartbeat, no-op message @@ -99,10 +104,20 @@ window.Conn = class TermConnection extends EventEmitter { return true } + /** Safely close the socket */ + closeSocket () { + if (this.ws) { + this.forceClosing = true + this.ws.close() + this.forceClosing = false + this.ws = null + } + } + init () { if (window._demo) { if (typeof window.demoInterface === 'undefined') { - alert('Demoing non-demo demo!') // this will catch mistakes when deploying to the website + alert('Demoing non-demo build!') // this will catch mistakes when deploying to the website } else { demoInterface.init(screen) showPage() @@ -110,9 +125,11 @@ window.Conn = class TermConnection extends EventEmitter { return } - clearTimeout(this.reconTimeout) + clearTimeout(this.reconnTimeout) clearTimeout(this.heartbeatTimeout) + this.closeSocket() + this.ws = new WebSocket('ws://' + _root + '/term/update.ws') this.ws.addEventListener('open', (...args) => this.onWSOpen(...args)) this.ws.addEventListener('close', (...args) => this.onWSClose(...args)) @@ -120,7 +137,7 @@ window.Conn = class TermConnection extends EventEmitter { console.log('Opening socket.') this.heartbeat() - this.emit('connect') + this.emit('open') } heartbeat () { @@ -129,20 +146,25 @@ window.Conn = class TermConnection extends EventEmitter { } onHeartbeatFail () { + this.closeSocket() + this.emit('silence') console.error('Heartbeat lost, probing server...') clearInterval(this.pingInterval) + this.pingInterval = setInterval(() => { console.log('> ping') this.emit('ping') $.get('http://' + _root + '/system/ping', (resp, status) => { if (status === 200) { clearInterval(this.pingInterval) - console.info('Server ready, reloading page...') + console.info('Server ready, opening socket…') this.emit('ping-success') - location.reload() + this.init() + // location.reload() } else this.emit('ping-fail', status) }, { - timeout: 100 + timeout: 100, + loader: false // we have loader on-screen }) }, 1000) } diff --git a/js/term_screen.js b/js/term_screen.js index acdbc04..a0e8420 100644 --- a/js/term_screen.js +++ b/js/term_screen.js @@ -72,6 +72,8 @@ window.TermScreen = class TermScreen extends EventEmitter { this._debug = null + this.contentLoaded = false + this.canvas = mk('canvas') this.ctx = this.canvas.getContext('2d') @@ -1136,16 +1138,16 @@ window.TermScreen = class TermScreen extends EventEmitter { ctx.setTransform(devicePixelRatio, 0, 0, devicePixelRatio, 0, 0) ctx.clearRect(0, 0, screenWidth, screenHeight) - ctx.font = `40px ${fontFamily}` + ctx.font = `24px ${fontFamily}` ctx.fillStyle = '#fff' ctx.textAlign = 'center' ctx.textBaseline = 'middle' - ctx.fillText(statusScreen.title || '', screenWidth / 2, screenHeight / 2 - 20) + ctx.fillText(statusScreen.title || '', screenWidth / 2, screenHeight / 2 - 50) if (statusScreen.loading) { // show loading spinner ctx.save() - ctx.translate(screenWidth / 2, screenHeight / 2 + 50) + ctx.translate(screenWidth / 2, screenHeight / 2 + 20) ctx.strokeStyle = '#fff' ctx.lineWidth = 5 @@ -1194,6 +1196,12 @@ window.TermScreen = class TermScreen extends EventEmitter { // Uncomment to capture screen content for the demo page // console.log(JSON.stringify(`S${str}`)) + if (!this.contentLoaded) { + let errmsg = qs('#load-failed') + if (errmsg) errmsg.parentNode.removeChild(errmsg) + this.contentLoaded = true + } + // window size const newHeight = parse2B(str, i) const newWidth = parse2B(str, i + 2) diff --git a/sass/pages/_term.scss b/sass/pages/_term.scss index 4fafc9b..bb781c9 100755 --- a/sass/pages/_term.scss +++ b/sass/pages/_term.scss @@ -85,6 +85,13 @@ body.term { } } +#load-failed { + color: red; + font-size: 18px; + font-weight: bold; + margin: 10px 5px 14px 5px; +} + #term-nav { padding-top: 1.5em; text-align: center;