From 3c15e016307cf737a7d072593e5c17384ffeb404 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Fri, 2 Mar 2018 15:54:15 -0500 Subject: [PATCH] Auto-fixes: UX Improvements (#2077) * Whitelist `conversation_search_view` for ESLint * Autofix `conversation_search_view` * Remove Vim modeline * Whitelist globals for ESLint * Ignore unnamed module IIFE * Whitelist legacy `then` expressions * Extract `isSearchable` Fixes line length violations. * Remove unused constant * Remove unnecessary escaping for parens Suggested by ESLint `no-useless-escape` rule. * :art: Organize file list * Whitelist `inbox_view` for ESLint * Autofix `inbox_view` * Remove Vim modeline * Add function names * Whitelist globals for ESLint * Fix lint errors * :abc: `options` properties * :art: Improve `then` chain formatting * Consider `js/*.js` files as scripts not modules Forces use of 'use strict' directive per ESLint. * Ignore unnamed module IIFE * Fix function argument line breaks --- .eslintignore | 4 +- app/menu.js | 18 +- js/.eslintrc | 3 + js/modules/.eslintrc | 3 + js/views/attachment_view.js | 2 + js/views/conversation_search_view.js | 318 ++++++++-------- js/views/inbox_view.js | 545 ++++++++++++++------------- 7 files changed, 461 insertions(+), 432 deletions(-) diff --git a/.eslintignore b/.eslintignore index c4a708004091..8773f6f9f90f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -17,7 +17,9 @@ test/views/*.js # ES2015+ files !js/background.js !js/models/conversations.js -!js/views/file_input_view.js !js/views/attachment_view.js +!js/views/conversation_search_view.js +!js/views/file_input_view.js +!js/views/inbox_view.js !main.js !prepare_build.js diff --git a/app/menu.js b/app/menu.js index e021ee6c2d98..5ed1b86aa4d6 100644 --- a/app/menu.js +++ b/app/menu.js @@ -1,14 +1,14 @@ function createTemplate(options, messages) { const { - showDebugLog, - showAbout, - openReleaseNotes, - openNewBugForm, - openSupportPage, openForums, - setupWithImport, + openNewBugForm, + openReleaseNotes, + openSupportPage, setupAsNewDevice, setupAsStandalone, + setupWithImport, + showAbout, + showDebugLog, } = options; const template = [{ @@ -156,11 +156,11 @@ function createTemplate(options, messages) { function updateForMac(template, messages, options) { const { - showWindow, - showAbout, - setupWithImport, setupAsNewDevice, setupAsStandalone, + setupWithImport, + showAbout, + showWindow, } = options; // Remove About item and separator from Help menu, since it's on the first menu diff --git a/js/.eslintrc b/js/.eslintrc index f12ba539239b..abe7cd23fcdd 100644 --- a/js/.eslintrc +++ b/js/.eslintrc @@ -3,4 +3,7 @@ "browser": true, "node": false }, + "parserOptions": { + "sourceType": "script" + } } diff --git a/js/modules/.eslintrc b/js/modules/.eslintrc index 99263e496f1f..b540ae7dfd55 100644 --- a/js/modules/.eslintrc +++ b/js/modules/.eslintrc @@ -6,5 +6,8 @@ }, "globals": { "console": true + }, + "parserOptions": { + "sourceType": "module" } } diff --git a/js/views/attachment_view.js b/js/views/attachment_view.js index 03e477dc33d3..b42987284507 100644 --- a/js/views/attachment_view.js +++ b/js/views/attachment_view.js @@ -11,6 +11,8 @@ // eslint-disable-next-line func-names (function () { + 'use strict'; + const ESCAPE_KEY_CODE = 27; const FileView = Whisper.View.extend({ diff --git a/js/views/conversation_search_view.js b/js/views/conversation_search_view.js index 5c5c45dd64dc..3083a15a1222 100644 --- a/js/views/conversation_search_view.js +++ b/js/views/conversation_search_view.js @@ -1,167 +1,171 @@ -/* - * vim: ts=4:sw=4:expandtab - */ +/* global ConversationController: false */ +/* global i18n: false */ +/* global Whisper: false */ + +// eslint-disable-next-line func-names (function () { - 'use strict'; - window.Whisper = window.Whisper || {}; + 'use strict'; - Whisper.NewContactView = Whisper.View.extend({ - templateName: 'new-contact', - className: 'conversation-list-item contact', - events: { - 'click': 'validate' - }, - initialize: function() { - this.listenTo(this.model, 'change', this.render); // auto update - }, - render_attributes: function() { - return { - number: i18n('newContact'), - title: this.model.getNumber(), - avatar: this.model.getAvatar(), - }; - }, - validate: function() { - if (this.model.isValid()) { - this.$el.addClass('valid'); - } else { - this.$el.removeClass('valid'); - } - }, - }); + window.Whisper = window.Whisper || {}; - Whisper.ConversationSearchView = Whisper.View.extend({ - className: 'conversation-search', - initialize: function(options) { - this.$input = options.input; - this.$new_contact = this.$('.new-contact'); + const isSearchable = conversation => + conversation.isSearchable(); - this.typeahead = new Whisper.ConversationCollection(); - // View to display the matched contacts from typeahead - this.typeahead_view = new Whisper.ConversationListView({ - collection : new Whisper.ConversationCollection([], { - comparator: function(m) { return m.getTitle().toLowerCase(); } - }) - }); - this.$el.append(this.typeahead_view.el); - this.initNewContact(); - //this.listenTo(this.collection, 'reset', this.filterContacts); - this.pending = Promise.resolve(); - }, + Whisper.NewContactView = Whisper.View.extend({ + templateName: 'new-contact', + className: 'conversation-list-item contact', + events: { + click: 'validate', + }, + initialize() { + this.listenTo(this.model, 'change', this.render); // auto update + }, + render_attributes() { + return { + number: i18n('newContact'), + title: this.model.getNumber(), + avatar: this.model.getAvatar(), + }; + }, + validate() { + if (this.model.isValid()) { + this.$el.addClass('valid'); + } else { + this.$el.removeClass('valid'); + } + }, + }); - events: { - 'click .new-contact': 'createConversation', - }, + Whisper.ConversationSearchView = Whisper.View.extend({ + className: 'conversation-search', + initialize(options) { + this.$input = options.input; + this.$new_contact = this.$('.new-contact'); - filterContacts: function() { - var query = this.$input.val().trim(); - if (query.length) { - if (this.maybeNumber(query)) { - this.new_contact_view.model.set('id', query); - this.new_contact_view.render().$el.show(); - this.new_contact_view.validate(); - this.hideHints(); + this.typeahead = new Whisper.ConversationCollection(); + // View to display the matched contacts from typeahead + this.typeahead_view = new Whisper.ConversationListView({ + collection: new Whisper.ConversationCollection([], { + comparator(m) { return m.getTitle().toLowerCase(); }, + }), + }); + this.$el.append(this.typeahead_view.el); + this.initNewContact(); + // this.listenTo(this.collection, 'reset', this.filterContacts); + this.pending = Promise.resolve(); + }, - } else { - this.new_contact_view.$el.hide(); - } - this.pending = this.pending.then(function() { - return this.typeahead.search(query).then(function() { - this.typeahead_view.collection.reset( - this.typeahead.filter(function(m) { - return m.isSearchable(); - }) - ); - }.bind(this)); - }.bind(this)); - this.trigger('show'); - } else { - this.resetTypeahead(); - } - }, + events: { + 'click .new-contact': 'createConversation', + }, - initNewContact: function() { - if (this.new_contact_view) { - this.new_contact_view.undelegateEvents(); - this.new_contact_view.$el.hide(); - } - // Creates a view to display a new contact - this.new_contact_view = new Whisper.NewContactView({ - el: this.$new_contact, - model: ConversationController.createTemporary({ - type: 'private' - }) - }).render(); - }, - - createConversation: function() { - var conversation = this.new_contact_view.model; - if (this.new_contact_view.model.isValid()) { - ConversationController.getOrCreateAndWait( - this.new_contact_view.model.id, - 'private' - ).then(function(conversation) { - this.trigger('open', conversation); - this.initNewContact(); - this.resetTypeahead(); - }.bind(this)); - } else { - this.new_contact_view.$('.number').text(i18n('invalidNumberError')); - this.$input.focus(); - } - }, - - reset: function() { - this.delegateEvents(); - this.typeahead_view.delegateEvents(); - this.new_contact_view.delegateEvents(); - this.resetTypeahead(); - }, - - resetTypeahead: function() { - this.hideHints(); - this.new_contact_view.$el.hide(); - this.$input.val('').focus(); - if (this.showAllContacts) { - this.typeahead.fetchAlphabetical().then(function() { - if (this.typeahead.length > 0) { - this.typeahead_view.collection.reset( - this.typeahead.filter(function(m) { - return m.isSearchable(); - }) - ); - } else { - this.showHints(); - } - }.bind(this)); - this.trigger('show'); - } else { - this.typeahead_view.collection.reset([]); - this.trigger('hide'); - } - }, - - showHints: function() { - if (!this.hintView) { - this.hintView = new Whisper.HintView({ - className: 'contact placeholder', - content: i18n('newPhoneNumber') - }).render(); - this.hintView.$el.insertAfter(this.$input); - } - this.hintView.$el.show(); - }, - - hideHints: function() { - if (this.hintView) { - this.hintView.remove(); - this.hintView = null; - } - }, - - maybeNumber: function(number) { - return number.replace(/[\s-.\(\)]*/g,'').match(/^\+?[0-9]*$/); + filterContacts() { + const query = this.$input.val().trim(); + if (query.length) { + if (this.maybeNumber(query)) { + this.new_contact_view.model.set('id', query); + this.new_contact_view.render().$el.show(); + this.new_contact_view.validate(); + this.hideHints(); + } else { + this.new_contact_view.$el.hide(); } - }); + // NOTE: Temporarily allow `then` until we convert the entire file + // to `async` / `await`: + /* eslint-disable more/no-then */ + this.pending = this.pending.then(() => + this.typeahead.search(query).then(() => { + this.typeahead_view.collection.reset(this.typeahead.filter(isSearchable)); + })); + /* eslint-enable more/no-then */ + this.trigger('show'); + } else { + this.resetTypeahead(); + } + }, -})(); + initNewContact() { + if (this.new_contact_view) { + this.new_contact_view.undelegateEvents(); + this.new_contact_view.$el.hide(); + } + // Creates a view to display a new contact + this.new_contact_view = new Whisper.NewContactView({ + el: this.$new_contact, + model: ConversationController.createTemporary({ + type: 'private', + }), + }).render(); + }, + + createConversation() { + if (this.new_contact_view.model.isValid()) { + // NOTE: Temporarily allow `then` until we convert the entire file + // to `async` / `await`: + // eslint-disable-next-line more/no-then + ConversationController.getOrCreateAndWait( + this.new_contact_view.model.id, + 'private' + ).then((conversation) => { + this.trigger('open', conversation); + this.initNewContact(); + this.resetTypeahead(); + }); + } else { + this.new_contact_view.$('.number').text(i18n('invalidNumberError')); + this.$input.focus(); + } + }, + + reset() { + this.delegateEvents(); + this.typeahead_view.delegateEvents(); + this.new_contact_view.delegateEvents(); + this.resetTypeahead(); + }, + + resetTypeahead() { + this.hideHints(); + this.new_contact_view.$el.hide(); + this.$input.val('').focus(); + if (this.showAllContacts) { + // NOTE: Temporarily allow `then` until we convert the entire file + // to `async` / `await`: + // eslint-disable-next-line more/no-then + this.typeahead.fetchAlphabetical().then(() => { + if (this.typeahead.length > 0) { + this.typeahead_view.collection.reset(this.typeahead.filter(isSearchable)); + } else { + this.showHints(); + } + }); + this.trigger('show'); + } else { + this.typeahead_view.collection.reset([]); + this.trigger('hide'); + } + }, + + showHints() { + if (!this.hintView) { + this.hintView = new Whisper.HintView({ + className: 'contact placeholder', + content: i18n('newPhoneNumber'), + }).render(); + this.hintView.$el.insertAfter(this.$input); + } + this.hintView.$el.show(); + }, + + hideHints() { + if (this.hintView) { + this.hintView.remove(); + this.hintView = null; + } + }, + + maybeNumber(number) { + return number.replace(/[\s-.()]*/g, '').match(/^\+?[0-9]*$/); + }, + }); +}()); diff --git a/js/views/inbox_view.js b/js/views/inbox_view.js index aa92c17893f3..b45801c14072 100644 --- a/js/views/inbox_view.js +++ b/js/views/inbox_view.js @@ -1,283 +1,298 @@ -/* - * vim: ts=4:sw=4:expandtab - */ +/* global ConversationController: false */ +/* global extension: false */ +/* global getInboxCollection: false */ +/* global i18n: false */ +/* global Whisper: false */ + +// eslint-disable-next-line func-names (function () { - 'use strict'; + 'use strict'; - window.Whisper = window.Whisper || {}; + window.Whisper = window.Whisper || {}; - Whisper.ConversationStack = Whisper.View.extend({ - className: 'conversation-stack', - open: function(conversation) { - var id = 'conversation-' + conversation.cid; - if (id !== this.el.firstChild.id) { - this.$el.first().find('video, audio').each(function() { - this.pause(); - }); - var $el = this.$('#'+id); - if ($el === null || $el.length === 0) { - var view = new Whisper.ConversationView({ - model: conversation, - window: this.model.window - }); - $el = view.$el; - } - $el.prependTo(this.el); - conversation.trigger('opened'); - } + Whisper.ConversationStack = Whisper.View.extend({ + className: 'conversation-stack', + open(conversation) { + const id = `conversation-${conversation.cid}`; + if (id !== this.el.firstChild.id) { + this.$el.first().find('video, audio').each(function pauseMedia() { + this.pause(); + }); + let $el = this.$(`#${id}`); + if ($el === null || $el.length === 0) { + const view = new Whisper.ConversationView({ + model: conversation, + window: this.model.window, + }); + // eslint-disable-next-line prefer-destructuring + $el = view.$el; } - }); + $el.prependTo(this.el); + conversation.trigger('opened'); + } + }, + }); - Whisper.FontSizeView = Whisper.View.extend({ - defaultSize: 14, - maxSize: 30, - minSize: 14, - initialize: function() { - this.currentSize = this.defaultSize; - this.render(); - }, - events: { 'keydown': 'zoomText' }, - zoomText: function(e) { - if (!e.ctrlKey) { - return; - } - var keyCode = e.which || e.keyCode; - var maxSize = 22; // if bigger text goes outside send-message textarea - var minSize = 14; - if (keyCode === 189 || keyCode == 109) { - if (this.currentSize > minSize) { - this.currentSize--; - } - } else if (keyCode === 187 || keyCode == 107) { - if (this.currentSize < maxSize) { - this.currentSize++; - } - } - this.render(); - }, - render: function() { - this.$el.css('font-size', this.currentSize + 'px'); + Whisper.FontSizeView = Whisper.View.extend({ + defaultSize: 14, + maxSize: 30, + minSize: 14, + initialize() { + this.currentSize = this.defaultSize; + this.render(); + }, + events: { keydown: 'zoomText' }, + zoomText(e) { + if (!e.ctrlKey) { + return; + } + const keyCode = e.which || e.keyCode; + const maxSize = 22; // if bigger text goes outside send-message textarea + const minSize = 14; + if (keyCode === 189 || keyCode === 109) { + if (this.currentSize > minSize) { + this.currentSize -= 1; } - }); - - - Whisper.AppLoadingScreen = Whisper.View.extend({ - templateName: 'app-loading-screen', - className: 'app-loading-screen', - updateProgress: function(count) { - if (count > 0) { - var message = i18n('loadingMessages', count.toString()); - this.$('.message').text(message); - } - }, - render_attributes: { - message: i18n('loading') + } else if (keyCode === 187 || keyCode === 107) { + if (this.currentSize < maxSize) { + this.currentSize += 1; } - }); + } + this.render(); + }, + render() { + this.$el.css('font-size', `${this.currentSize}px`); + }, + }); - Whisper.InboxView = Whisper.View.extend({ - templateName: 'two-column', - className: 'inbox index', - initialize: function (options) { - options = options || {}; - this.ready = false; - this.render(); - this.$el.attr('tabindex', '1'); - new Whisper.FontSizeView({ el: this.$el }); - this.conversation_stack = new Whisper.ConversationStack({ - el: this.$('.conversation-stack'), - model: { window: options.window } - }); + Whisper.AppLoadingScreen = Whisper.View.extend({ + templateName: 'app-loading-screen', + className: 'app-loading-screen', + updateProgress(count) { + if (count > 0) { + const message = i18n('loadingMessages', count.toString()); + this.$('.message').text(message); + } + }, + render_attributes: { + message: i18n('loading'), + }, + }); - if (!options.initialLoadComplete) { - this.appLoadingScreen = new Whisper.AppLoadingScreen(); - this.appLoadingScreen.render(); - this.appLoadingScreen.$el.prependTo(this.el); - this.startConnectionListener(); - } + Whisper.InboxView = Whisper.View.extend({ + templateName: 'two-column', + className: 'inbox index', + initialize(options = {}) { + this.ready = false; + this.render(); + this.$el.attr('tabindex', '1'); - var inboxCollection = getInboxCollection(); + // eslint-disable-next-line no-new + new Whisper.FontSizeView({ el: this.$el }); - inboxCollection.on('messageError', function() { - this.networkStatusView.render(); - }.bind(this)); + this.conversation_stack = new Whisper.ConversationStack({ + el: this.$('.conversation-stack'), + model: { window: options.window }, + }); - this.inboxListView = new Whisper.ConversationListView({ - el : this.$('.inbox'), - collection : inboxCollection - }).render(); + if (!options.initialLoadComplete) { + this.appLoadingScreen = new Whisper.AppLoadingScreen(); + this.appLoadingScreen.render(); + this.appLoadingScreen.$el.prependTo(this.el); + this.startConnectionListener(); + } - this.inboxListView.listenTo( - inboxCollection, - 'add change:timestamp change:name change:number', - this.inboxListView.updateLocation + const inboxCollection = getInboxCollection(); + + inboxCollection.on('messageError', () => { + this.networkStatusView.render(); + }); + + this.inboxListView = new Whisper.ConversationListView({ + el: this.$('.inbox'), + collection: inboxCollection, + }).render(); + + this.inboxListView.listenTo( + inboxCollection, + 'add change:timestamp change:name change:number', + this.inboxListView.updateLocation + ); + this.inboxListView.listenTo( + inboxCollection, + 'remove', + this.inboxListView.removeItem + ); + + this.searchView = new Whisper.ConversationSearchView({ + el: this.$('.search-results'), + input: this.$('input.search'), + }); + + this.searchView.$el.hide(); + + this.listenTo(this.searchView, 'hide', function toggleVisibility() { + this.searchView.$el.hide(); + this.inboxListView.$el.show(); + }); + this.listenTo(this.searchView, 'show', function toggleVisibility() { + this.searchView.$el.show(); + this.inboxListView.$el.hide(); + }); + this.listenTo( + this.searchView, + 'open', + this.openConversation.bind(this, null) + ); + + this.networkStatusView = new Whisper.NetworkStatusView(); + this.$el.find('.network-status-container') + .append(this.networkStatusView.render().el); + + extension.windows.onClosed(() => { + this.inboxListView.stopListening(); + }); + + if (extension.expired()) { + const banner = new Whisper.ExpiredAlertBanner().render(); + banner.$el.prependTo(this.$el); + this.$el.addClass('expired'); + } + }, + render_attributes: { + welcomeToSignal: i18n('welcomeToSignal'), + selectAContact: i18n('selectAContact'), + searchForPeopleOrGroups: i18n('searchForPeopleOrGroups'), + settings: i18n('settings'), + restartSignal: i18n('restartSignal'), + }, + events: { + click: 'onClick', + 'click #header': 'focusHeader', + 'click .conversation': 'focusConversation', + 'click .global-menu .hamburger': 'toggleMenu', + 'click .showSettings': 'showSettings', + 'select .gutter .conversation-list-item': 'openConversation', + 'input input.search': 'filterContacts', + 'click .restart-signal': window.restart, + 'show .lightbox': 'showLightbox', + }, + startConnectionListener() { + this.interval = setInterval(() => { + const status = window.getSocketStatus(); + switch (status) { + case WebSocket.CONNECTING: + break; + case WebSocket.OPEN: + clearInterval(this.interval); + // if we've connected, we can wait for real empty event + this.interval = null; + break; + case WebSocket.CLOSING: + case WebSocket.CLOSED: + clearInterval(this.interval); + this.interval = null; + // if we failed to connect, we pretend we got an empty event + this.onEmpty(); + break; + default: + console.log( + 'Whisper.InboxView::startConnectionListener:', + 'Unknown web socket status:', status ); - this.inboxListView.listenTo( - inboxCollection, - 'remove', - this.inboxListView.removeItem - ); - - this.searchView = new Whisper.ConversationSearchView({ - el : this.$('.search-results'), - input : this.$('input.search') - }); - - this.searchView.$el.hide(); - - this.listenTo(this.searchView, 'hide', function() { - this.searchView.$el.hide(); - this.inboxListView.$el.show(); - }); - this.listenTo(this.searchView, 'show', function() { - this.searchView.$el.show(); - this.inboxListView.$el.hide(); - }); - this.listenTo(this.searchView, 'open', - this.openConversation.bind(this, null)); - - this.networkStatusView = new Whisper.NetworkStatusView(); - this.$el.find('.network-status-container').append(this.networkStatusView.render().el); - - extension.windows.onClosed(function() { - this.inboxListView.stopListening(); - }.bind(this)); - - if (extension.expired()) { - var banner = new Whisper.ExpiredAlertBanner().render(); - banner.$el.prependTo(this.$el); - this.$el.addClass('expired'); - } - }, - render_attributes: { - welcomeToSignal : i18n('welcomeToSignal'), - selectAContact : i18n('selectAContact'), - searchForPeopleOrGroups : i18n('searchForPeopleOrGroups'), - settings : i18n('settings'), - restartSignal : i18n('restartSignal'), - }, - events: { - 'click': 'onClick', - 'click #header': 'focusHeader', - 'click .conversation': 'focusConversation', - 'click .global-menu .hamburger': 'toggleMenu', - 'click .showSettings': 'showSettings', - 'select .gutter .conversation-list-item': 'openConversation', - 'input input.search': 'filterContacts', - 'click .restart-signal': window.restart, - 'show .lightbox': 'showLightbox', - }, - startConnectionListener: function() { - this.interval = setInterval(function() { - var status = window.getSocketStatus(); - switch(status) { - case WebSocket.CONNECTING: - break; - case WebSocket.OPEN: - clearInterval(this.interval); - // if we've connected, we can wait for real empty event - this.interval = null; - break; - case WebSocket.CLOSING: - case WebSocket.CLOSED: - clearInterval(this.interval); - this.interval = null; - // if we failed to connect, we pretend we got an empty event - this.onEmpty(); - break; - } - }.bind(this), 1000); - }, - onEmpty: function() { - var view = this.appLoadingScreen; - if (view) { - this.appLoadingScreen = null; - view.remove(); - } - }, - onProgress: function(count) { - var view = this.appLoadingScreen; - if (view) { - view.updateProgress(count); - } - }, - focusConversation: function(e) { - if (e && this.$(e.target).closest('.placeholder').length) { - return; - } - - this.$('#header, .gutter').addClass('inactive'); - this.$('.conversation-stack').removeClass('inactive'); - }, - focusHeader: function() { - this.$('.conversation-stack').addClass('inactive'); - this.$('#header, .gutter').removeClass('inactive'); - this.$('.conversation:first .menu').trigger('close'); - }, - reloadBackgroundPage: function() { - window.location.reload(); - }, - showSettings: function() { - var view = new Whisper.SettingsView(); - view.$el.appendTo(this.el); - }, - filterContacts: function(e) { - this.searchView.filterContacts(e); - var input = this.$('input.search'); - if (input.val().length > 0) { - input.addClass('active'); - var textDir = window.getComputedStyle(input[0]).direction; - if (textDir === 'ltr') { - input.removeClass('rtl').addClass('ltr'); - } else if (textDir === 'rtl') { - input.removeClass('ltr').addClass('rtl'); - } - } else { - input.removeClass('active'); - } - }, - openConversation: function(e, conversation) { - this.searchView.hideHints(); - if (conversation) { - conversation = ConversationController.get(conversation.id); - this.conversation_stack.open(conversation); - this.focusConversation(); - } - }, - toggleMenu: function() { - this.$('.global-menu .menu-list').toggle(); - }, - showLightbox: function(e) { - this.$el.append(e.target); - }, - closeRecording: function(e) { - if (e && this.$(e.target).closest('.capture-audio').length > 0 ) { - return; - } - this.$('.conversation:first .recorder').trigger('close'); - }, - closeMenu: function(e) { - if (e && this.$(e.target).parent('.global-menu').length > 0 ) { - return; - } - - this.$('.global-menu .menu-list').hide(); - }, - onClick: function(e) { - this.closeMenu(e); - this.closeRecording(e); + break; } - }); + }, 1000); + }, + onEmpty() { + const view = this.appLoadingScreen; + if (view) { + this.appLoadingScreen = null; + view.remove(); + } + }, + onProgress(count) { + const view = this.appLoadingScreen; + if (view) { + view.updateProgress(count); + } + }, + focusConversation(e) { + if (e && this.$(e.target).closest('.placeholder').length) { + return; + } - Whisper.ExpiredAlertBanner = Whisper.View.extend({ - templateName: 'expired_alert', - className: 'expiredAlert clearfix', - render_attributes: function() { - return { - expiredWarning: i18n('expiredWarning'), - upgrade: i18n('upgrade'), - }; + this.$('#header, .gutter').addClass('inactive'); + this.$('.conversation-stack').removeClass('inactive'); + }, + focusHeader() { + this.$('.conversation-stack').addClass('inactive'); + this.$('#header, .gutter').removeClass('inactive'); + this.$('.conversation:first .menu').trigger('close'); + }, + reloadBackgroundPage() { + window.location.reload(); + }, + showSettings() { + const view = new Whisper.SettingsView(); + view.$el.appendTo(this.el); + }, + filterContacts(e) { + this.searchView.filterContacts(e); + const input = this.$('input.search'); + if (input.val().length > 0) { + input.addClass('active'); + const textDir = window.getComputedStyle(input[0]).direction; + if (textDir === 'ltr') { + input.removeClass('rtl').addClass('ltr'); + } else if (textDir === 'rtl') { + input.removeClass('ltr').addClass('rtl'); } - }); -})(); + } else { + input.removeClass('active'); + } + }, + openConversation(e, conversation) { + this.searchView.hideHints(); + if (conversation) { + this.conversation_stack.open(ConversationController.get(conversation.id)); + this.focusConversation(); + } + }, + toggleMenu() { + this.$('.global-menu .menu-list').toggle(); + }, + showLightbox(e) { + this.$el.append(e.target); + }, + closeRecording(e) { + if (e && this.$(e.target).closest('.capture-audio').length > 0) { + return; + } + this.$('.conversation:first .recorder').trigger('close'); + }, + closeMenu(e) { + if (e && this.$(e.target).parent('.global-menu').length > 0) { + return; + } + + this.$('.global-menu .menu-list').hide(); + }, + onClick(e) { + this.closeMenu(e); + this.closeRecording(e); + }, + }); + + Whisper.ExpiredAlertBanner = Whisper.View.extend({ + templateName: 'expired_alert', + className: 'expiredAlert clearfix', + render_attributes() { + return { + expiredWarning: i18n('expiredWarning'), + upgrade: i18n('upgrade'), + }; + }, + }); +}());