mirror of
https://github.com/zulip/zulip.git
synced 2025-11-14 10:57:58 +00:00
Chevron icon on each message now causes a dropdown menu; hover on message for info
As does the hotkey "i". It's somewhat less appropriate because it's all actions, but it's where our "info" menu used to be, and we can workshop a better one. "a" feels weird to me, but maybe it's just me. You can also hover on the .message_content to see a popover with extra message details This is for Trac #1334. (imported from commit f8fbf70c8502370a78159e24f3cf9589fb9d384f)
This commit is contained in:
@@ -103,6 +103,10 @@
|
||||
<td class="hotkey">?</td>
|
||||
<td class="definition">Open keyboard shortcut help</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="hotkey">i</td>
|
||||
<td class="definition">Open message actions menu</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
@@ -162,6 +162,7 @@ exports.start = function (msg_type, opts) {
|
||||
return;
|
||||
}
|
||||
|
||||
ui.hide_actions_dropdown();
|
||||
$("#compose_close").show();
|
||||
$("#compose_controls").hide();
|
||||
$('.message_comp').show();
|
||||
|
||||
@@ -18,6 +18,14 @@ var directional_hotkeys = {
|
||||
'home': {getrow: rows.first_visible, direction: -1, charCode: 0} // Home
|
||||
};
|
||||
|
||||
var actions_dropdown_hotkeys = [
|
||||
'down_arrow',
|
||||
'up_arrow',
|
||||
'vim_up',
|
||||
'vim_down',
|
||||
'enter'
|
||||
];
|
||||
|
||||
function get_event_name(e) {
|
||||
if ((e.which === 9) && e.shiftKey) {
|
||||
return 'shift_tab';
|
||||
@@ -72,6 +80,8 @@ function get_event_name(e) {
|
||||
return 'narrow_by_subject';
|
||||
case 99: // 'c'
|
||||
return 'compose';
|
||||
case 105: // 'i'
|
||||
return 'message_actions';
|
||||
case 106: // 'j'
|
||||
return 'vim_down';
|
||||
case 107: // 'k'
|
||||
@@ -103,6 +113,11 @@ function process_hotkey(e) {
|
||||
|
||||
var next_row, dirkey;
|
||||
|
||||
if (ui.actions_menu_currently_shown() && actions_dropdown_hotkeys.indexOf(event_name) !== -1) {
|
||||
ui.actions_menu_handle_keyboard(event_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle a few keys specially when the send button is focused.
|
||||
if ($('#compose-send-button').is(':focus')) {
|
||||
if (event_name === 'backspace') {
|
||||
@@ -215,6 +230,10 @@ function process_hotkey(e) {
|
||||
|
||||
|
||||
switch (event_name) {
|
||||
case 'message_actions':
|
||||
var id = current_msg_list.selected_id();
|
||||
ui.show_actions_dropdown($(".selected_message .message_actions_hover")[0], id);
|
||||
return true;
|
||||
case 'page_up':
|
||||
if (viewport.at_top() && !current_msg_list.empty()) {
|
||||
current_msg_list.select_id(current_msg_list.first().id, {then_scroll: false});
|
||||
@@ -232,8 +251,8 @@ function process_hotkey(e) {
|
||||
}
|
||||
return true;
|
||||
case 'escape': // Esc: close actions popup, cancel compose, clear a find, or un-narrow
|
||||
if (ui.actions_currently_popped()) {
|
||||
ui.hide_actions_popover();
|
||||
if (ui.actions_menu_currently_shown()) {
|
||||
ui.hide_actions_dropdown();
|
||||
} else if (compose.composing()) {
|
||||
compose.cancel();
|
||||
} else {
|
||||
|
||||
@@ -473,43 +473,120 @@ function hack_for_floating_recipient_bar() {
|
||||
floating_recipient.offset(offset);
|
||||
}
|
||||
|
||||
var current_actions_popover_elem;
|
||||
function show_actions_popover(element, id) {
|
||||
var last_popover_elem = current_actions_popover_elem;
|
||||
ui.hide_actions_popover();
|
||||
if (last_popover_elem !== undefined
|
||||
&& last_popover_elem.get()[0] === element) {
|
||||
// We want it to be the case that a user can dismiss a popover
|
||||
// by clicking on the same element that caused the popover.
|
||||
var current_actions_dropdown_elem;
|
||||
exports.show_actions_dropdown = function (element, id) {
|
||||
element = $(element).parent()[0];
|
||||
|
||||
if (current_actions_dropdown_elem === element
|
||||
&& ui.actions_menu_currently_shown()) {
|
||||
// We want it to be the case that a user can dismiss a dropdown
|
||||
// by clicking on the same element that caused the dropdown.
|
||||
ui.hide_actions_dropdown();
|
||||
return;
|
||||
}
|
||||
|
||||
ui.hide_actions_dropdown();
|
||||
|
||||
// since we clicked on this element
|
||||
current_msg_list.select_id(id);
|
||||
var elt = $(element);
|
||||
if (elt.data('popover') === undefined) {
|
||||
|
||||
if ($('.dropdown-menu', elt).length === 0) {
|
||||
compose.cancel();
|
||||
ui.hide_message_info_popover();
|
||||
var message = current_msg_list.get(id);
|
||||
var args = {
|
||||
message: message,
|
||||
can_edit_message: message.sent_by_me,
|
||||
narrowed: narrow.active()
|
||||
};
|
||||
var rendered_dropdown_menu = $(templates.render('actions_dropdown_content', args));
|
||||
|
||||
rendered_dropdown_menu.appendTo(elt);
|
||||
current_actions_dropdown_elem = element;
|
||||
}
|
||||
$(elt.children()[0]).dropdown('toggle');
|
||||
};
|
||||
|
||||
exports.actions_menu_handle_keyboard = function (key) {
|
||||
var items = $('li:not(.divider):visible a', current_actions_dropdown_elem);
|
||||
var index = items.index(items.filter(':focus'));
|
||||
|
||||
if (key === "enter" && index >= 0 && index < items.length) {
|
||||
return items.eq(index).trigger('click');
|
||||
}
|
||||
if (index === -1) {
|
||||
index = 0;
|
||||
}
|
||||
else if ((key === 'down_arrow' || key === 'vim_down') && index < items.length - 1) {
|
||||
++index;
|
||||
}
|
||||
else if ((key === 'up_arrow' || key === 'vim_up') && index > 0) {
|
||||
--index;
|
||||
}
|
||||
items.eq(index).focus();
|
||||
};
|
||||
|
||||
exports.hide_actions_dropdown = function () {
|
||||
if (ui.actions_menu_currently_shown()) {
|
||||
$(current_actions_dropdown_elem).removeClass('open');
|
||||
$(current_actions_dropdown_elem).children().eq(0).off('click.data-api.dropdown');
|
||||
$('.dropdown-menu', current_actions_dropdown_elem).remove();
|
||||
current_actions_dropdown_elem = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
exports.actions_menu_currently_shown = function () {
|
||||
return $(current_actions_dropdown_elem).hasClass('open');
|
||||
};
|
||||
|
||||
|
||||
var current_message_info_popover_elem;
|
||||
var current_message_info_hover_timeout;
|
||||
function show_message_info_popover(element, id, event_type) {
|
||||
|
||||
ui.hide_message_info_popover();
|
||||
|
||||
if (event_type === 'mouseleave') {
|
||||
return;
|
||||
}
|
||||
|
||||
var elt = $(element);
|
||||
timerender.set_full_datetime(current_msg_list.get(id),
|
||||
elt.closest(".message_row").find(".message_time"));
|
||||
|
||||
var message = current_msg_list.get(id);
|
||||
var can_edit = message.sent_by_me;
|
||||
var args = {
|
||||
message: message,
|
||||
can_edit_message: can_edit,
|
||||
can_edit_message: message.sent_by_me,
|
||||
narrowed: narrow.active()
|
||||
};
|
||||
|
||||
var ypos = elt.offset().top - viewport.scrollTop();
|
||||
elt.popover({
|
||||
placement: (ypos > (viewport.height() - 300)) ? 'top' : 'bottom',
|
||||
title: templates.render('actions_popover_title', args),
|
||||
content: templates.render('actions_popover_content', args),
|
||||
placement: 'left',
|
||||
title: templates.render('message_info_popover_title', args),
|
||||
content: templates.render('message_info_popover_content', args),
|
||||
trigger: "manual"
|
||||
});
|
||||
|
||||
current_message_info_hover_timeout = window.setTimeout(function() {
|
||||
elt.popover("show");
|
||||
current_actions_popover_elem = elt;
|
||||
current_message_info_popover_elem = elt;
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
exports.hide_message_info_popover = function () {
|
||||
if (current_message_info_hover_timeout !== undefined) {
|
||||
window.clearTimeout(current_message_info_hover_timeout);
|
||||
current_message_info_hover_timeout = undefined;
|
||||
}
|
||||
|
||||
if (current_message_info_popover_elem !== undefined) {
|
||||
current_message_info_popover_elem.popover("destroy");
|
||||
current_message_info_popover_elem = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
function update_message_flag(message, flag_name, set_flag) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
@@ -560,17 +637,6 @@ function toggle_star(row_id) {
|
||||
change_message_star(message, message.starred);
|
||||
}
|
||||
|
||||
exports.hide_actions_popover = function () {
|
||||
if (ui.actions_currently_popped()) {
|
||||
current_actions_popover_elem.popover("destroy");
|
||||
current_actions_popover_elem = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
exports.actions_currently_popped = function () {
|
||||
return current_actions_popover_elem !== undefined;
|
||||
};
|
||||
|
||||
function update_gravatars() {
|
||||
$.each($(".gravatar-profile"), function (index, profile) {
|
||||
// Avatar URLs will have at least one param, so & is safe here.
|
||||
@@ -662,6 +728,7 @@ function condense(row) {
|
||||
show_more_link(row);
|
||||
}
|
||||
|
||||
|
||||
function uncondense(row) {
|
||||
var content = row.find(".message_content");
|
||||
content.removeClass("condensed");
|
||||
@@ -1087,20 +1154,26 @@ $(function () {
|
||||
message_unhover();
|
||||
});
|
||||
|
||||
$("#main_div").on("mouseover", ".actions_hover", function (e) {
|
||||
$("#main_div").on("mouseover", ".message_actions_hover", function (e) {
|
||||
var row = $(this).closest(".message_row");
|
||||
row.addClass("actions_hovered");
|
||||
});
|
||||
|
||||
$("#main_div").on("mouseout", ".actions_hover", function (e) {
|
||||
$("#main_div").on("mouseout", ".message_actions_hover", function (e) {
|
||||
var row = $(this).closest(".message_row");
|
||||
row.removeClass("actions_hovered");
|
||||
});
|
||||
|
||||
$("#main_div").on("click", ".actions_hover", function (e) {
|
||||
$("#main_div").on("hover", ".messagebox:not(.message_controls)", function (e) {
|
||||
var row = $(this).closest(".message_row");
|
||||
e.stopPropagation();
|
||||
show_actions_popover(this, rows.id(row));
|
||||
show_message_info_popover(this, rows.id(row), e.type);
|
||||
});
|
||||
|
||||
$("#main_div").on("click", ".message_actions_hover", function (e) {
|
||||
var row = $(this).closest(".message_row");
|
||||
e.stopPropagation();
|
||||
exports.show_actions_dropdown(this, rows.id(row));
|
||||
});
|
||||
|
||||
$("#main_div").on("click", ".star", function (e) {
|
||||
@@ -1433,30 +1506,35 @@ $(function () {
|
||||
|
||||
$('body').on('click', '.respond_button', function (e) {
|
||||
respond_to_message({trigger: 'popover respond'});
|
||||
ui.hide_actions_popover();
|
||||
ui.hide_actions_dropdown();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
$('body').on('click', '.respond_personal_button', function (e) {
|
||||
respond_to_message({reply_type: 'personal', trigger: 'popover respond pm'});
|
||||
ui.hide_actions_popover();
|
||||
ui.hide_actions_dropdown();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
$('body').on('click', '.popover_narrow_by_subject_button', function (e) {
|
||||
var msgid = $(e.currentTarget).data('msgid');
|
||||
ui.hide_actions_popover();
|
||||
ui.hide_actions_dropdown();
|
||||
narrow.by_subject(msgid, {trigger: 'popover'});
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
$('body').on('click', '.popover_narrow_by_recipient_button', function (e) {
|
||||
var msgid = $(e.currentTarget).data('msgid');
|
||||
ui.hide_actions_popover();
|
||||
ui.hide_actions_dropdown();
|
||||
narrow.by_recipient(msgid, {trigger: 'popover'});
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
$('body').on('click', '.popover_narrow_by_time_travel_button', function (e) {
|
||||
var msgid = $(e.currentTarget).data('msgid');
|
||||
ui.hide_actions_popover();
|
||||
ui.hide_actions_dropdown();
|
||||
narrow.by_time_travel(msgid, {trigger: 'popover'});
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
$('body').on('click', '.popover_toggle_collapse', function (e) {
|
||||
@@ -1464,7 +1542,7 @@ $(function () {
|
||||
var row = rows.get(msgid, current_msg_list.table_name);
|
||||
var message = current_msg_list.get(rows.id(row));
|
||||
|
||||
ui.hide_actions_popover();
|
||||
ui.hide_actions_dropdown();
|
||||
|
||||
if (message.collapsed) {
|
||||
uncollapse(row);
|
||||
@@ -1472,6 +1550,7 @@ $(function () {
|
||||
collapse(row);
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
$('body').on('click', '.edit_subject', function (e) {
|
||||
@@ -1483,8 +1562,9 @@ $(function () {
|
||||
$('body').on('click', '.popover_edit_message', function (e) {
|
||||
var msgid = $(e.currentTarget).data('msgid');
|
||||
var row = rows.get(msgid, current_msg_list.table_name);
|
||||
ui.hide_actions_popover();
|
||||
ui.hide_actions_dropdown();
|
||||
message_edit.start(row);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
$("body").on("click", ".message_edit_save", function (e) {
|
||||
@@ -1539,7 +1619,7 @@ $(function () {
|
||||
$("body").on('click', function (e) {
|
||||
// Dismiss the popover if the user has clicked outside it
|
||||
if ($('.popover-inner').has(e.target).length === 0) {
|
||||
ui.hide_actions_popover();
|
||||
ui.hide_actions_dropdown();
|
||||
if (stream_sidebar_popup_shown_this_click === false ) {
|
||||
ui.hide_stream_sidebar_popover();
|
||||
}
|
||||
|
||||
@@ -649,11 +649,11 @@ background-color: #ffe4e0;
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.actions_hovered .sender_name {
|
||||
.message_hovered .sender_name {
|
||||
color: #0088CC;
|
||||
}
|
||||
|
||||
.actions_hovered .inline_profile_picture {
|
||||
.message_hovered .inline_profile_picture {
|
||||
border-color: #0088CC;
|
||||
}
|
||||
|
||||
@@ -1893,3 +1893,8 @@ li.expanded_subject {
|
||||
.message-pane {
|
||||
padding-left: 0.3em;
|
||||
}
|
||||
|
||||
.dropdown-menu a {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,7 @@
|
||||
{{! Contents of the "message actions" popup }}
|
||||
<ul class="nav nav-list actions_popover">
|
||||
<div class="popover_info">
|
||||
<li>Sent by <b>{{message.sender_full_name}}</b></li>
|
||||
<li class='my_email'>{{message.sender_email}}</li>
|
||||
<hr />
|
||||
|
||||
<li>{{message.full_date_str}}</li>
|
||||
<li>{{message.full_time_str}}</li>
|
||||
{{#if message.historical}}
|
||||
<li class="small">(Message sent when you were not subscribed)</li>
|
||||
{{/if}}
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
<ul class="dropdown-menu pull-right">
|
||||
<li>
|
||||
<a class="respond_button">
|
||||
<a href="#" class="respond_button">
|
||||
<i class="icon-share-alt"></i>
|
||||
{{#if message.is_stream}}
|
||||
Reply to this subject on stream <b>{{message.stream}}</b>
|
||||
@@ -25,7 +12,7 @@
|
||||
</li>
|
||||
{{#unless message.is_private}}
|
||||
<li>
|
||||
<a class="respond_personal_button">
|
||||
<a href="#" class="respond_personal_button">
|
||||
<i class="icon-user"></i> Reply to <b>{{message.sender_full_name}}</b> only
|
||||
</a>
|
||||
</li>
|
||||
@@ -33,14 +20,14 @@
|
||||
|
||||
{{#if message.is_stream}}
|
||||
<li>
|
||||
<a class="popover_narrow_by_subject_button" data-msgid="{{message.id}}">
|
||||
<a href="#" class="popover_narrow_by_subject_button" data-msgid="{{message.id}}">
|
||||
<i class="icon-bullhorn"></i>
|
||||
Narrow to this subject on stream <b>{{message.stream}}</b>
|
||||
</a>
|
||||
</li>
|
||||
{{else}}
|
||||
<li>
|
||||
<a class="popover_narrow_by_recipient_button" data-msgid="{{message.id}}">
|
||||
<a href="#" class="popover_narrow_by_recipient_button" data-msgid="{{message.id}}">
|
||||
<i class="icon-user"></i>
|
||||
Narrow to this private message conversation
|
||||
</a>
|
||||
@@ -49,7 +36,7 @@
|
||||
|
||||
{{#if narrowed}}
|
||||
<li>
|
||||
<a class="popover_narrow_by_time_travel_button" data-msgid="{{message.id}}">
|
||||
<a href="#" class="popover_narrow_by_time_travel_button" data-msgid="{{message.id}}">
|
||||
<i class="icon-time"></i> Narrow to messages around this time
|
||||
</a>
|
||||
</li>
|
||||
@@ -57,14 +44,14 @@
|
||||
|
||||
{{#if can_edit_message}}
|
||||
<li>
|
||||
<a class="popover_edit_message" data-msgid="{{message.id}}">
|
||||
<a href="#" class="popover_edit_message" data-msgid="{{message.id}}">
|
||||
<i class="icon-pencil"></i> Edit this message
|
||||
</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
|
||||
<li>
|
||||
<a class="popover_toggle_collapse" data-msgid="{{message.id}}">
|
||||
<a href="#" class="popover_toggle_collapse" data-msgid="{{message.id}}">
|
||||
<i class="{{#if message.collapsed}}icon-plus{{else}}icon-minus{{/if}}"></i>
|
||||
{{#if message.collapsed}}Un-collapse{{else}}Collapse{{/if}} this message
|
||||
</a>
|
||||
@@ -54,9 +54,9 @@
|
||||
class="message_row{{^is_stream}} private-message{{/is_stream}}{{#include_sender}} include-sender{{/include_sender}}{{#contains_mention}} mention{{/contains_mention}}{{#include_footer}} last_message{{/include_footer}}">
|
||||
<td class="messagebox_colorblock{{^is_stream}} message_header_private_message{{/is_stream}}" style="background-color: {{background_color}};"><span class="pointer_icon"><i class="icon-vector-caret-right"></i></span></td>
|
||||
<td class="messagebox{{^include_sender}} prev_is_same_sender{{/include_sender}}{{^is_stream}} private-message{{/is_stream}}">
|
||||
<div class="message_top_line">
|
||||
<div class="message_top_line dropdown">
|
||||
{{#include_sender}}
|
||||
<span class="message_sender actions_hover">
|
||||
<span class="message_sender sender_actions_hover">
|
||||
{{! See ../js/notifications.js for another user of avatar_url. }}
|
||||
<div class="inline_profile_picture"
|
||||
style="background-image: url('{{small_avatar_url}}');"/>
|
||||
@@ -69,7 +69,7 @@
|
||||
<span class="message_star {{#if starred}}icon-vector-star{{else}}icon-vector-star empty-star{{/if}}"
|
||||
title="{{#if starred}}Unstar{{else}}Star{{/if}} this message"></i>
|
||||
</div>
|
||||
<div class="info actions_hover">
|
||||
<div class="info message_actions_hover">
|
||||
<i class="icon-vector-angle-down"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{{! Contents of the "message actions" popup }}
|
||||
<ul class="nav nav-list actions_popover">
|
||||
<div class="popover_info">
|
||||
<li>Sent by <b>{{message.sender_full_name}}</b></li>
|
||||
<li class='my_email'>{{message.sender_email}}</li>
|
||||
<hr />
|
||||
|
||||
<li>{{message.full_date_str}}</li>
|
||||
<li>{{message.full_time_str}}</li>
|
||||
{{#if message.historical}}
|
||||
<li class="small">(Message sent when you were not subscribed)</li>
|
||||
{{/if}}
|
||||
</div>
|
||||
</ul>
|
||||
Reference in New Issue
Block a user