From 3ed009dfed9babc81cdb1485ea5e79e4e6721b66 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Tue, 13 Sep 2016 19:31:40 +0200 Subject: [PATCH] show error-view instead of yellow notification on content loading errors --- js/controller/foldercontroller.js | 13 +++-- js/controller/messagecontroller.js | 3 +- js/templates/error.html | 4 ++ js/util/errormessagefactory.js | 79 ++++++++++++++++++++++++++++++ js/views/appview.js | 10 ++++ js/views/errorview.js | 44 +++++++++++++++++ js/views/foldercontent.js | 9 ++++ js/views/navigation-accounts.js | 4 +- 8 files changed, 161 insertions(+), 5 deletions(-) create mode 100644 js/templates/error.html create mode 100644 js/util/errormessagefactory.js create mode 100644 js/views/errorview.js diff --git a/js/controller/foldercontroller.js b/js/controller/foldercontroller.js index 900d9c762..f81770e84 100644 --- a/js/controller/foldercontroller.js +++ b/js/controller/foldercontroller.js @@ -24,6 +24,7 @@ define(function(require) { var _ = require('underscore'); var Radio = require('radio'); var FolderService = require('service/folderservice'); + var ErrorMessageFactory = require('util/errormessagefactory'); Radio.message.on('fetch:bodies', fetchBodies); @@ -45,6 +46,7 @@ define(function(require) { * @param {Account} account * @param {Folder} folder * @param {boolean} noSelect + * @param {string} searchQuery * @returns {undefined} */ function loadFolderMessages(account, folder, noSelect, searchQuery) { @@ -108,10 +110,15 @@ define(function(require) { }); $.when(loadingMessages).fail(function() { + var icon; + if (folder.get('specialRole')) { + icon = 'icon-' + folder.get('specialRole'); + } + Radio.ui.trigger('content:error', ErrorMessageFactory.getRandomFolderErrorMessage(folder), icon); + // Set the old folder as being active - var folder = require('state').currentFolder; - Radio.folder.trigger('setactive', account, folder); - Radio.ui.trigger('error:show', t('mail', 'Error while loading messages.')); + var oldFolder = require('state').currentFolder; + Radio.folder.trigger('setactive', account, oldFolder); }); } } diff --git a/js/controller/messagecontroller.js b/js/controller/messagecontroller.js index 1bc574c87..f2cff129f 100644 --- a/js/controller/messagecontroller.js +++ b/js/controller/messagecontroller.js @@ -24,6 +24,7 @@ define(function(require) { var _ = require('underscore'); var OC = require('OC'); var Radio = require('radio'); + var ErrorMessageFactory = require('util/errormessagefactory'); Radio.message.on('load', function(account, folder, message, options) { //FIXME: don't rely on global state vars @@ -101,7 +102,7 @@ define(function(require) { } }); $.when(fetchingMessage).fail(function() { - Radio.ui.trigger('error:show', t('mail', 'Error while loading the selected message.')); + Radio.ui.trigger('message:error', ErrorMessageFactory.getRandomMessageErrorMessage()); }); } diff --git a/js/templates/error.html b/js/templates/error.html new file mode 100644 index 000000000..bdb5d8197 --- /dev/null +++ b/js/templates/error.html @@ -0,0 +1,4 @@ +
+ {{#if icon}}
{{/if}} +

{{{ text }}}

+
\ No newline at end of file diff --git a/js/util/errormessagefactory.js b/js/util/errormessagefactory.js new file mode 100644 index 000000000..dda4140f0 --- /dev/null +++ b/js/util/errormessagefactory.js @@ -0,0 +1,79 @@ +/** + * @author Christoph Wurst + * + * Mail + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +define(function(require) { + 'use strict'; + + var smileys = [ + ':-(', + ':-/', + ':-\\', + ':-|', + ':\'-(', + ':\'-/', + ':\'-\\', + ':\'-|' + ]; + + function getRandomSmiley() { + return smileys[Math.floor(Math.random() * smileys.length)] + } + + /** + * @param {Folder} folder + * @returns {string} + */ + function getRandomFolderErrorMessage(folder) { + var folderName = folder.get('name'); + var rawTexts = [ + t('mail', 'Could not load {tag}{name}{endtag}', { + name: folderName + }), + t('mail', 'We couldn’t load {tag}{name}{endtag}', { + name: folderName + }), + t('mail', 'There was a problem loading {tag}{name}{endtag}', { + name: folderName + }) + ]; + var texts = _.map(rawTexts, function(text) { + return text.replace('{tag}', '').replace('{endtag}', ''); + }); + var text = texts[Math.floor(Math.random() * texts.length)] + return text + ' ' + getRandomSmiley(); + } + + /** + * @returns {string} + */ + function getRandomMessageErrorMessage() { + var texts = [ + t('mail', 'We couldn’t load your message'), + t('mail', 'Unable to load the desired message'), + t('mail', 'There was a problem loading the message') + ]; + var text = texts[Math.floor(Math.random() * texts.length)] + return text + ' ' + getRandomSmiley(); + } + + return { + getRandomFolderErrorMessage: getRandomFolderErrorMessage, + getRandomMessageErrorMessage: getRandomMessageErrorMessage + }; +}); diff --git a/js/views/appview.js b/js/views/appview.js index 16827b956..3e964fab3 100644 --- a/js/views/appview.js +++ b/js/views/appview.js @@ -21,6 +21,7 @@ define(function(require) { var FolderContentView = require('views/foldercontent'); var NavigationAccountsView = require('views/navigation-accounts'); var SettingsView = require('views/settings'); + var ErrorView = require('views/errorview'); var LoadingView = require('views/loadingview'); var NavigationView = require('views/navigation'); var SetupView = require('views/setup'); @@ -30,6 +31,7 @@ define(function(require) { require('views/helper'); var ContentType = Object.freeze({ + ERROR: -2, LOADING: -1, FOLDER_CONTENT: 0, SETUP: 1, @@ -54,6 +56,7 @@ define(function(require) { this.listenTo(Radio.ui, 'error:show', this.showError); this.listenTo(Radio.ui, 'setup:show', this.showSetup); this.listenTo(Radio.ui, 'foldercontent:show', this.showFolderContent); + this.listenTo(Radio.ui, 'content:error', this.showContentError); this.listenTo(Radio.ui, 'content:loading', this.showContentLoading); this.listenTo(Radio.ui, 'title:update', this.updateTitle); this.listenTo(Radio.ui, 'accountsettings:show', this.showAccountSettings); @@ -165,6 +168,13 @@ define(function(require) { this.content.show(new FolderContentView(options)); }, + showContentError: function(text, icon) { + this.activeContent = ContentType.ERROR; + this.content.show(new ErrorView({ + text: text, + icon: icon + })); + }, showContentLoading: function(text) { this.activeContent = ContentType.LOADING; this.content.show(new LoadingView({ diff --git a/js/views/errorview.js b/js/views/errorview.js new file mode 100644 index 000000000..65826fdfc --- /dev/null +++ b/js/views/errorview.js @@ -0,0 +1,44 @@ +/** + * @author Christoph Wurst + * + * Mail + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +define(function(require) { + 'use strict'; + + var Handlebars = require('handlebars'); + var Marionette = require('marionette'); + var ErrorTemplate = require('text!templates/error.html'); + + var ErrorView = Marionette.ItemView.extend({ + id: 'emptycontent', + className: 'container', + template: Handlebars.compile(ErrorTemplate), + templateHelpers: function() { + return { + text: this.text, + icon: this.icon + }; + }, + initialize: function(options) { + this.text = options.text || t('mail', 'An unknown error occurred'); + this.icon = options.icon || 'icon-mail'; + } + }); + + return ErrorView; +}); diff --git a/js/views/foldercontent.js b/js/views/foldercontent.js index ab593354b..ef2aab856 100644 --- a/js/views/foldercontent.js +++ b/js/views/foldercontent.js @@ -29,10 +29,12 @@ define(function(require) { var ComposerView = require('views/composer'); var MessageView = require('views/message'); var MessagesView = require('views/messagesview'); + var ErrorView = require('views/errorview'); var LoadingView = require('views/loadingview'); var MessageContentTemplate = require('text!templates/foldercontent.html'); var DetailView = Object.freeze({ + ERROR: -2, MESSAGE: 1, COMPOSER: 2 }); @@ -55,6 +57,7 @@ define(function(require) { this.searchQuery = options.searchQuery; this.listenTo(Radio.ui, 'message:show', this.onShowMessage); + this.listenTo(Radio.ui, 'message:error', this.onShowError); this.listenTo(Radio.ui, 'composer:show', this.onShowComposer); this.listenTo(Radio.ui, 'composer:leave', this.onComposerLeave); this.listenTo(Radio.keyboard, 'keyup', this.onKeyUp); @@ -89,6 +92,12 @@ define(function(require) { Radio.ui.trigger('messagesview:messageflag:set', message.id, 'unseen', false); }, + onShowError: function(errorMessage) { + this.message.show(new ErrorView({ + text: errorMessage + })); + this.detailView = DetailView.ERROR; + }, onShowComposer: function(data) { $('.tooltip').remove(); $('#mail_new_message').prop('disabled', true); diff --git a/js/views/navigation-accounts.js b/js/views/navigation-accounts.js index c64027f21..50f8430a7 100644 --- a/js/views/navigation-accounts.js +++ b/js/views/navigation-accounts.js @@ -49,7 +49,9 @@ define(function(require) { }); }); - folder.set('active', true); + if (folder) { + folder.set('active', true); + } }, /** * @returns {undefined}