/* global Whisper, extension, Backbone, moment, i18n */ // eslint-disable-next-line func-names (function() { 'use strict'; window.Whisper = window.Whisper || {}; const DISCONNECTED_DELAY = 30000; Whisper.NetworkStatusView = Whisper.View.extend({ className: 'network-status', templateName: 'networkStatus', initialize() { this.$el.hide(); this.renderIntervalHandle = setInterval(this.update.bind(this), 5000); extension.windows.onClosed(() => { clearInterval(this.renderIntervalHandle); }); setTimeout(this.finishConnectingGracePeriod.bind(this), 5000); this.withinConnectingGracePeriod = true; this.setSocketReconnectInterval(null); window.addEventListener('online', this.update.bind(this)); window.addEventListener('offline', this.update.bind(this)); this.model = new Backbone.Model(); this.listenTo(this.model, 'change', this.onChange); this.connectedTimer = null; }, onReconnectTimer() { this.setSocketReconnectInterval(60000); }, finishConnectingGracePeriod() { this.withinConnectingGracePeriod = false; }, setSocketReconnectInterval(millis) { this.socketReconnectWaitDuration = moment.duration(millis); }, navigatorOnLine() { return navigator.onLine; }, getSocketStatus() { return window.getSocketStatus(); }, getNetworkStatus(shortCircuit = false) { let message = ''; let instructions = ''; let hasInterruption = false; let action = null; let buttonClass = null; const socketStatus = this.getSocketStatus(); switch (socketStatus) { case WebSocket.CONNECTING: message = i18n('connecting'); this.setSocketReconnectInterval(null); window.clearTimeout(this.connectedTimer); this.connectedTimer = null; break; case WebSocket.OPEN: this.setSocketReconnectInterval(null); window.clearTimeout(this.connectedTimer); this.connectedTimer = null; break; case WebSocket.CLOSED: // Intentional fallthrough case WebSocket.CLOSING: // Intentional fallthrough default: { const markOffline = () => { message = i18n('disconnected'); instructions = i18n('checkNetworkConnection'); hasInterruption = true; }; if (shortCircuit) { // Used to skip the timer for testing markOffline(); break; } if (!this.connectedTimer) { // Mark offline if disconnected for 30 seconds this.connectedTimer = window.setTimeout(() => { markOffline(); }, DISCONNECTED_DELAY); } break; } } if ( socketStatus === WebSocket.CONNECTING && !this.withinConnectingGracePeriod ) { hasInterruption = true; } if (this.socketReconnectWaitDuration.asSeconds() > 0) { instructions = i18n('attemptingReconnection', [ this.socketReconnectWaitDuration.asSeconds(), ]); } if (!this.navigatorOnLine()) { hasInterruption = true; message = i18n('offline'); instructions = i18n('checkNetworkConnection'); } else if (!Whisper.Registration.isDone()) { hasInterruption = true; message = i18n('unlinked'); instructions = i18n('unlinkedWarning'); action = i18n('relink'); buttonClass = 'openInstaller'; } return { message, instructions, hasInterruption, action, buttonClass, }; }, update() { const status = this.getNetworkStatus(); this.model.set(status); }, render_attributes() { return this.model.attributes; }, onChange() { this.render(); if (this.model.attributes.hasInterruption) { this.$el.slideDown(); } else { this.$el.hide(); } }, }); })();