(function() { 'use strict'; window.Whisper = window.Whisper || {}; Whisper.AppView = Backbone.View.extend({ initialize: function(options) { this.inboxView = null; this.installView = null; this.applyTheme(); this.applyHideMenu(); }, events: { 'click .openInstaller': 'openInstaller', // NetworkStatusView has this button openInbox: 'openInbox', 'change-theme': 'applyTheme', 'change-hide-menu': 'applyHideMenu', }, applyTheme: function() { var theme = storage.get('theme-setting') || 'android'; this.$el .removeClass('ios') .removeClass('android-dark') .removeClass('android') .addClass(theme); }, applyHideMenu: function() { var hideMenuBar = storage.get('hide-menu-bar', false); window.setAutoHideMenuBar(hideMenuBar); window.setMenuBarVisibility(!hideMenuBar); }, openView: function(view) { this.el.innerHTML = ''; this.el.append(view.el); this.delegateEvents(); }, openDebugLog: function() { this.closeDebugLog(); this.debugLogView = new Whisper.DebugLogView(); this.debugLogView.$el.appendTo(this.el); }, closeDebugLog: function() { if (this.debugLogView) { this.debugLogView.remove(); this.debugLogView = null; } }, openImporter: function() { window.addSetupMenuItems(); this.resetViews(); var importView = (this.importView = new Whisper.ImportView()); this.listenTo( importView, 'light-import', this.finishLightImport.bind(this) ); this.openView(this.importView); }, finishLightImport: function() { var options = { hasExistingData: true, }; this.openInstaller(options); }, closeImporter: function() { if (this.importView) { this.importView.remove(); this.importView = null; } }, openInstaller: function(options) { options = options || {}; // If we're in the middle of import, we don't want to show the menu options // allowing the user to switch to other ways to set up the app. If they // switched back and forth in the middle of a light import, they'd lose all // that imported data. if (!options.hasExistingData) { window.addSetupMenuItems(); } this.resetViews(); var installView = (this.installView = new Whisper.InstallView(options)); this.openView(this.installView); }, closeInstaller: function() { if (this.installView) { this.installView.remove(); this.installView = null; } }, openStandalone: function() { if (window.config.environment !== 'production') { window.addSetupMenuItems(); this.resetViews(); this.standaloneView = new Whisper.StandaloneRegistrationView(); this.openView(this.standaloneView); } }, closeStandalone: function() { if (this.standaloneView) { this.standaloneView.remove(); this.standaloneView = null; } }, resetViews: function() { this.closeInstaller(); this.closeImporter(); this.closeStandalone(); }, openInbox: function(options) { options = options || {}; // The inbox can be created before the 'empty' event fires or afterwards. If // before, it's straightforward: the onEmpty() handler below updates the // view directly, and we're in good shape. If we create the inbox late, we // need to be sure that the current value of initialLoadComplete is provided // so its loading screen doesn't stick around forever. // Two primary techniques at play for this situation: // - background.js has two openInbox() calls, and passes initalLoadComplete // directly via the options parameter. // - in other situations openInbox() will be called with no options. So this // view keeps track of whether onEmpty() has ever been called with // this.initialLoadComplete. An example of this: on a phone-pairing setup. _.defaults(options, { initialLoadComplete: this.initialLoadComplete }); console.log('open inbox'); this.closeInstaller(); if (!this.inboxView) { // We create the inbox immediately so we don't miss an update to // this.initialLoadComplete between the start of this method and the // creation of inboxView. this.inboxView = new Whisper.InboxView({ model: self, window: window, initialLoadComplete: options.initialLoadComplete, }); return ConversationController.loadPromise().then( function() { this.openView(this.inboxView); }.bind(this) ); } else { if (!$.contains(this.el, this.inboxView.el)) { this.openView(this.inboxView); } window.focus(); // FIXME return Promise.resolve(); } }, onEmpty: function() { var view = this.inboxView; this.initialLoadComplete = true; if (view) { view.onEmpty(); } }, onProgress: function(count) { var view = this.inboxView; if (view) { view.onProgress(count); } }, openConversation: function(conversation) { if (conversation) { this.openInbox().then( function() { this.inboxView.openConversation(null, conversation); }.bind(this) ); } }, }); })();