From 344b0af9c6c2f6531504dbc8363faa54ce9c6440 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak <alec@alec.pl> Date: Wed, 04 May 2016 07:33:01 -0400 Subject: [PATCH] Indicate that a collapsed thread has flagged children (#5013) --- program/js/app.js | 136 ++++++++++++++++++++++++++++++++------------- 1 files changed, 97 insertions(+), 39 deletions(-) diff --git a/program/js/app.js b/program/js/app.js index 9a9a1d6..1ec2dd4 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -295,7 +295,7 @@ else if (this.env.action == 'compose') { this.env.address_group_stack = []; this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'cancel', - 'toggle-editor', 'list-adresses', 'pushgroup', 'search', 'reset-search', 'extwin', + 'toggle-editor', 'list-addresses', 'pushgroup', 'search', 'reset-search', 'extwin', 'insert-response', 'save-response', 'menu-open', 'menu-close']; if (this.env.drafts_mailbox) @@ -339,8 +339,15 @@ // init message compose form this.init_messageform(); } - else if (this.env.action == 'get') + else if (this.env.action == 'get') { this.enable_command('download', 'print', true); + if (this.env.is_message) { + this.enable_command('reply', 'reply-all', 'edit', 'viewsource', + 'forward', 'forward-inline', 'forward-attachment', true); + if (this.env.list_post) + this.enable_command('reply-list', true); + } + } // show printing dialog else if (this.env.action == 'print' && this.env.uid && !this.env.is_pgp_content && !this.env.pgp_mime_part @@ -381,7 +388,7 @@ if (this.gui_objects.addressbookslist) { this.gui_objects.folderlist = this.gui_objects.addressbookslist; - this.enable_command('list-adresses', true); + this.enable_command('list-addresses', true); } // ask user to send MDN @@ -581,7 +588,12 @@ this.display_message.apply(this, this.pending_message); // init treelist widget - if (this.gui_objects.folderlist && window.rcube_treelist_widget) { + if (this.gui_objects.folderlist && window.rcube_treelist_widget + // some plugins may load rcube_treelist_widget and there's one case + // when this will cause problems - addressbook widget in compose, + // which already has been initialized using rcube_list_widget + && this.gui_objects.folderlist != this.gui_objects.addressbookslist + ) { this.treelist = new rcube_treelist_widget(this.gui_objects.folderlist, { selectable: true, id_prefix: 'rcmli', @@ -1019,7 +1031,7 @@ break; } - this.goto_url('get', qstring+'&_download=1', false); + this.goto_url('get', qstring+'&_download=1', false, true); break; case 'select-all': @@ -1161,7 +1173,7 @@ this.change_identity($("[name='_from']")[0], true); break; - case 'list-adresses': + case 'list-addresses': this.list_contacts(props); this.enable_command('add-recipient', false); break; @@ -1206,13 +1218,13 @@ this.open_window(this.env.comm_path + url, true, true); } } - else if (this.env.action == 'get') { + else if (this.env.action == 'get' && !this.env.is_message) { this.gui_objects.messagepartframe.contentWindow.print(); } else if (uid = this.get_single_uid()) { url = this.url('print', this.params_from_uid(uid, {_safe: this.env.safemode ? 1 : 0})); if (this.open_window(url, true, true)) { - if (this.env.action != 'show') + if (this.env.action != 'show' && this.env.action != 'get') this.mark_message('read', uid); } } @@ -1225,10 +1237,10 @@ case 'download': if (this.env.action == 'get') { - location.href = location.href.replace(/_frame=/, '_download='); + location.href = this.secure_url(location.href.replace(/_frame=/, '_download=')); } else if (uid = this.get_single_uid()) { - this.goto_url('viewsource', this.params_from_uid(uid, {_save: 1})); + this.goto_url('viewsource', this.params_from_uid(uid, {_save: 1}), false, true); } break; @@ -1316,13 +1328,13 @@ case 'export': if (this.contact_list.rowcount > 0) { - this.goto_url('export', { _source: this.env.source, _gid: this.env.group, _search: this.env.search_request }); + this.goto_url('export', { _source: this.env.source, _gid: this.env.group, _search: this.env.search_request }, false, true); } break; case 'export-selected': if (this.contact_list.rowcount > 0) { - this.goto_url('export', { _source: this.env.source, _gid: this.env.group, _cid: this.contact_list.get_selection().join(',') }); + this.goto_url('export', { _source: this.env.source, _gid: this.env.group, _cid: this.contact_list.get_selection().join(',') }, false, true); } break; @@ -1357,7 +1369,7 @@ if (!aborted && this.triggerEvent('after'+command, props) === false) ret = false; - this.triggerEvent('actionafter', { props:props, action:command, aborted:aborted }); + this.triggerEvent('actionafter', { props:props, action:command, aborted:aborted, ret:ret }); return ret === false ? false : obj ? false : true; }; @@ -1437,7 +1449,7 @@ if (task == 'mail') url += '&_mbox=INBOX'; else if (task == 'logout' && !this.env.server_error) { - url += '&_token=' + this.env.request_token; + url = this.secure_url(url); this.clear_compose_data(); } @@ -1485,6 +1497,12 @@ return url + '?' + name + '=' + value; }; + + // append CSRF protection token to the given url + this.secure_url = function(url) + { + return this.add_url(url, '_token', this.env.request_token); + }, this.is_framed = function() { @@ -2020,8 +2038,9 @@ flagged: flags.flagged?1:0, has_children: flags.has_children?1:0, depth: flags.depth?flags.depth:0, - unread_children: flags.unread_children?flags.unread_children:0, - parent_uid: flags.parent_uid?flags.parent_uid:0, + unread_children: flags.unread_children || 0, + flagged_children: flags.flagged_children || 0, + parent_uid: flags.parent_uid || 0, selected: this.select_all_mode || this.message_list.in_selection(uid), ml: flags.ml?1:0, ctype: flags.ctype, @@ -2101,6 +2120,9 @@ if (flags.unread_children && flags.seen && !message.expanded) row_class += ' unroot'; + + if (flags.flagged_children && !message.expanded) + row_class += ' flaggedroot'; } tree += '<span id="msgicn'+row.id+'" class="'+css_class+status_class+'" title="'+status_label+'"></span>'; @@ -2138,7 +2160,7 @@ html = '<span class="attachment" title="'+label+'"></span>'; else if (/multipart\/report/.test(flags.ctype)) html = '<span class="report"></span>'; - else + else html = ' '; } else if (c == 'status') { @@ -2559,9 +2581,10 @@ { var row = this.message_list.rows[uid]; - // handle unread_children mark + // handle unread_children/flagged_children mark row.expanded = !row.expanded; this.set_unread_children(uid); + this.set_flagged_children(uid); row.expanded = !row.expanded; this.message_list.expand_row(e, uid); @@ -2694,7 +2717,13 @@ } else if (flag == 'unread' && p.has_children) { // unread_children may be undefined - p.unread_children = p.unread_children ? p.unread_children + 1 : 1; + p.unread_children = (p.unread_children || 0) + 1; + } + else if (flag == 'unflagged' && p.flagged_children) { + p.flagged_children--; + } + else if (flag == 'flagged' && p.has_children) { + p.flagged_children = (p.flagged_children || 0) + 1; } else { return; @@ -2702,6 +2731,7 @@ this.set_message_icon(root); this.set_unread_children(root); + this.set_flagged_children(root); }; // update thread indicators for all messages in a thread below the specified message @@ -2719,11 +2749,19 @@ if (!row.depth) // root message: decrease roots count count--; - else if (row.unread) { - // update unread_children for thread root + + // update unread_children for thread root + if (row.depth && row.unread) { parent = this.message_list.find_root(uid); rows[parent].unread_children--; this.set_unread_children(parent); + } + + // update unread_children for thread root + if (row.depth && row.flagged) { + parent = this.message_list.find_root(uid); + rows[parent].flagged_children--; + this.set_flagged_children(parent); } parent = row.parent_uid; @@ -2767,9 +2805,11 @@ row = row.nextSibling; } - // update unread_children for roots - for (r=0; r<roots.length; r++) + // update unread_children/flagged_children for roots + for (r=0; r<roots.length; r++) { this.set_unread_children(roots[r].uid); + this.set_flagged_children(roots[r].uid); + } return count; }; @@ -2868,6 +2908,9 @@ if (row.unread != status) this.update_thread_root(uid, status ? 'unread' : 'read'); } + else if (flag == 'flagged') { + this.update_thread_root(uid, status ? 'flagged' : 'unflagged'); + } if ($.inArray(flag, ['unread', 'deleted', 'replied', 'forwarded', 'flagged']) > -1) row[flag] = status; @@ -2899,10 +2942,20 @@ if (row.parent_uid) return; - if (!row.unread && row.unread_children && !row.expanded) - $(row.obj).addClass('unroot'); - else - $(row.obj).removeClass('unroot'); + var enable = !row.unread && row.unread_children && !row.expanded; + $(row.obj)[enable ? 'addClass' : 'removeClass']('unroot'); + }; + + // sets flaggedroot (flagged_children) class of parent row + this.set_flagged_children = function(uid) + { + var row = this.message_list.rows[uid]; + + if (row.parent_uid) + return; + + var enable = row.flagged_children && !row.expanded; + $(row.obj)[enable ? 'addClass' : 'removeClass']('flaggedroot'); }; // copy selected messages to the specified mailbox @@ -3466,6 +3519,12 @@ // enable encrypted compose toggle this.enable_command('compose-encrypted', !is_html); } + + // make sure to disable encryption button after toggling editor into HTML mode + this.addEventListener('actionafter', function(args) { + if (args.ret && args.action == 'toggle-editor') + ref.enable_command('compose-encrypted', !args.props.html); + }); } }; @@ -3962,7 +4021,7 @@ } if (!html_mode) { - pos = this.env.top_posting ? 0 : input_message.value.length; + pos = this.env.top_posting && this.env.compose_mode ? 0 : input_message.value.length; // add signature according to selected identity // if we have HTML editor, signature is added in a callback @@ -4283,8 +4342,6 @@ if (result) { // update internal format flag $("input[name='_is_html']").val(props.html ? 1 : 0); - // enable encrypted compose toggle - this.enable_command('compose-encrypted', !props.html); } return result; @@ -7819,8 +7876,6 @@ var url = '?_task=utils&_action=' + (format == 'html' ? 'html2text' : 'text2html'), lock = this.set_busy(true, 'converting'); - this.log('HTTP POST: ' + url); - $.ajax({ type: 'POST', url: url, data: text, contentType: 'application/octet-stream', error: function(o, status, err) { ref.http_error(o, status, err, lock); }, success: function(data) { @@ -7894,9 +7949,11 @@ } }; - this.goto_url = function(action, query, lock) + this.goto_url = function(action, query, lock, secure) { - this.redirect(this.url(action, query), lock); + var url = this.url(action, query) + if (secure) url = this.secure_url(url); + this.redirect(url, lock); }; this.location_href = function(url, target, frame) @@ -8000,22 +8057,23 @@ if (response.env) this.set_env(response.env); + var i; + // we have labels to add if (typeof response.texts === 'object') { - for (var name in response.texts) - if (typeof response.texts[name] === 'string') - this.add_label(name, response.texts[name]); + for (i in response.texts) + if (typeof response.texts[i] === 'string') + this.add_label(i, response.texts[i]); } // if we get javascript code from server -> execute it if (response.exec) { - this.log(response.exec); eval(response.exec); } // execute callback functions of plugins if (response.callbacks && response.callbacks.length) { - for (var i=0; i < response.callbacks.length; i++) + for (i=0; i < response.callbacks.length; i++) this.triggerEvent(response.callbacks[i][0], response.callbacks[i][1]); } -- Gitblit v1.9.1