mirror of
https://github.com/zulip/zulip.git
synced 2025-11-10 17:07:07 +00:00
frontend: Change 'reply' button label to reflect selected message.
The 'reply' button shows the stream>topic or recipient(s) of the selected message, for better UX. It also expands to fill the remaining horizontal space in the button bar -- this should help make it easier for new users to figure out how to reply. Finally, it uses "Message" instead of "Reply", to better match the compose box. Fixes #17940.
This commit is contained in:
88
frontend_tests/node_tests/compose_closed_ui.js
Normal file
88
frontend_tests/node_tests/compose_closed_ui.js
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
const {strict: assert} = require("assert");
|
||||||
|
|
||||||
|
const {mock_cjs, mock_esm, set_global, zrequire} = require("../zjsunit/namespace");
|
||||||
|
const {run_test} = require("../zjsunit/test");
|
||||||
|
const $ = require("../zjsunit/zjquery");
|
||||||
|
|
||||||
|
// Mocking and stubbing things
|
||||||
|
mock_cjs("jquery", $);
|
||||||
|
set_global("document", "document-stub");
|
||||||
|
const message_lists = mock_esm("../../static/js/message_lists");
|
||||||
|
|
||||||
|
// Code we're actually using/testing
|
||||||
|
const compose_closed_ui = zrequire("compose_closed_ui");
|
||||||
|
const {MessageList} = zrequire("message_list");
|
||||||
|
|
||||||
|
// Helper test function
|
||||||
|
function test_reply_label(expected_label) {
|
||||||
|
const label = $(".compose_reply_button_recipient_label").text();
|
||||||
|
assert.equal(label, expected_label, "'" + label + "' did not match '" + expected_label + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
run_test("reply_label", () => {
|
||||||
|
// Mocking up a test message list
|
||||||
|
const filter = {
|
||||||
|
predicate: () => () => true,
|
||||||
|
};
|
||||||
|
const list = new MessageList({
|
||||||
|
filter,
|
||||||
|
});
|
||||||
|
message_lists.current = list;
|
||||||
|
list.add_messages([
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
stream: "first_stream",
|
||||||
|
topic: "first_topic",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
stream: "first_stream",
|
||||||
|
topic: "second_topic",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
stream: "second_stream",
|
||||||
|
topic: "third_topic",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
stream: "second_stream",
|
||||||
|
topic: "second_topic",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
display_reply_to: "some user",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
display_reply_to: "some user, other user",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const expected_labels = [
|
||||||
|
"#first_stream > first_topic",
|
||||||
|
"#first_stream > second_topic",
|
||||||
|
"#second_stream > third_topic",
|
||||||
|
"#second_stream > second_topic",
|
||||||
|
"some user",
|
||||||
|
"some user, other user",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Initialize the code we're testing.
|
||||||
|
compose_closed_ui.initialize();
|
||||||
|
|
||||||
|
// Run the tests!
|
||||||
|
let first = true;
|
||||||
|
for (const expected_label of expected_labels) {
|
||||||
|
if (first) {
|
||||||
|
list.select_id(list.first().id);
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
list.select_id(list.next());
|
||||||
|
}
|
||||||
|
test_reply_label(expected_label);
|
||||||
|
}
|
||||||
|
});
|
||||||
25
static/js/compose_closed_ui.js
Normal file
25
static/js/compose_closed_ui.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import $ from "jquery";
|
||||||
|
|
||||||
|
import * as message_lists from "./message_lists";
|
||||||
|
|
||||||
|
function update_reply_recipient_label() {
|
||||||
|
const message = message_lists.current.selected_message();
|
||||||
|
let recipient_label = "";
|
||||||
|
if (message) {
|
||||||
|
if (message.stream && message.topic) {
|
||||||
|
recipient_label = "#" + message.stream + " > " + message.topic;
|
||||||
|
} else if (message.display_reply_to) {
|
||||||
|
recipient_label = message.display_reply_to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$(".compose_reply_button_recipient_label").text(recipient_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move the closed-compose buttons click handlers here, probably.
|
||||||
|
|
||||||
|
export function initialize() {
|
||||||
|
// When the message selection changes, change the label on the Reply button.
|
||||||
|
$(document).on("message_selected.zulip", () => {
|
||||||
|
update_reply_recipient_label();
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import * as blueslip from "./blueslip";
|
|||||||
import * as bot_data from "./bot_data";
|
import * as bot_data from "./bot_data";
|
||||||
import * as click_handlers from "./click_handlers";
|
import * as click_handlers from "./click_handlers";
|
||||||
import * as compose from "./compose";
|
import * as compose from "./compose";
|
||||||
|
import * as compose_closed_ui from "./compose_closed_ui";
|
||||||
import * as compose_pm_pill from "./compose_pm_pill";
|
import * as compose_pm_pill from "./compose_pm_pill";
|
||||||
import * as composebox_typeahead from "./composebox_typeahead";
|
import * as composebox_typeahead from "./composebox_typeahead";
|
||||||
import * as condense from "./condense";
|
import * as condense from "./condense";
|
||||||
@@ -470,6 +471,7 @@ export function initialize_everything() {
|
|||||||
scroll_bar.initialize();
|
scroll_bar.initialize();
|
||||||
message_viewport.initialize();
|
message_viewport.initialize();
|
||||||
panels.initialize();
|
panels.initialize();
|
||||||
|
compose_closed_ui.initialize();
|
||||||
initialize_kitchen_sink_stuff();
|
initialize_kitchen_sink_stuff();
|
||||||
echo.initialize();
|
echo.initialize();
|
||||||
stream_edit.initialize();
|
stream_edit.initialize();
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
#compose_buttons {
|
#compose_buttons {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
.new_message_button {
|
.new_message_button {
|
||||||
padding-top: 1.1em;
|
margin-left: 4px;
|
||||||
|
|
||||||
.button.small {
|
.button.small {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
padding: 3px 10px;
|
padding: 3px 10px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
background-color: hsla(0, 0%, 0%, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.compose_mobile_button {
|
.compose_mobile_button {
|
||||||
@@ -16,10 +20,6 @@
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (width >= $sm_min) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-control-link {
|
.message-control-link {
|
||||||
@@ -29,27 +29,49 @@
|
|||||||
.alert-draft {
|
.alert-draft {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: hsl(170, 48%, 54%);
|
color: hsl(170, 48%, 54%);
|
||||||
padding: 3px 12px;
|
padding: 0 12px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (width < $sm_min) {
|
.reply_button_container {
|
||||||
.compose_stream_button,
|
flex: 1;
|
||||||
.compose_private_button {
|
min-width: 0;
|
||||||
display: none;
|
margin-left: 0;
|
||||||
|
|
||||||
|
.compose_reply_button {
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
.compose_reply_button_recipient_label {
|
||||||
|
color: hsl(215, 47%, 30%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mobile_button_container {
|
||||||
|
@media (width >= $sm_min) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream_button_container,
|
||||||
|
.private_button_container {
|
||||||
|
@media (width < $sm_min) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Main geometry for this element is in zulip.css */
|
/* Main geometry for this element is in zulip.css */
|
||||||
.compose-content {
|
.compose-content {
|
||||||
border-top: 1px solid hsla(0, 0%, 0%, 0.07);
|
border-top: 1px solid hsla(0, 0%, 0%, 0.07);
|
||||||
transition: background-color 200ms linear;
|
transition: background-color 200ms linear;
|
||||||
|
padding: 4px 4px 8px 4px;
|
||||||
padding: 8px 10px 8px 10px;
|
|
||||||
|
|
||||||
border-left: 1px solid hsl(0, 0%, 93%);
|
border-left: 1px solid hsl(0, 0%, 93%);
|
||||||
border-right: 1px solid hsl(0, 0%, 93%);
|
border-right: 1px solid hsl(0, 0%, 93%);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,17 @@ body.night-mode {
|
|||||||
background-color: hsl(212, 28%, 18%);
|
background-color: hsl(212, 28%, 18%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#compose_buttons .new_message_button .button.small {
|
||||||
|
background-color: hsla(0, 0%, 0%, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#compose_buttons
|
||||||
|
.reply_button_container
|
||||||
|
.compose_reply_button
|
||||||
|
.compose_reply_button_recipient_label {
|
||||||
|
color: hsl(215, 47%, 80%);
|
||||||
|
}
|
||||||
|
|
||||||
.compose-send-status-close {
|
.compose-send-status-close {
|
||||||
color: hsl(0, 0%, 100%);
|
color: hsl(0, 0%, 100%);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|||||||
@@ -5,20 +5,32 @@
|
|||||||
<span id="compose-reply-error-msg"></span>
|
<span id="compose-reply-error-msg"></span>
|
||||||
</div>
|
</div>
|
||||||
<div id="compose_buttons">
|
<div id="compose_buttons">
|
||||||
|
<span class="new_message_button reply_button_container">
|
||||||
|
<button type="button" class="button small rounded compose_reply_button"
|
||||||
|
id="left_bar_compose_reply_button_big"
|
||||||
|
title="{{t 'Reply' }} (r)">
|
||||||
|
<span class="compose_reply_button_label">
|
||||||
|
{{#tr}}
|
||||||
|
Message <z-recipient></z-recipient>
|
||||||
|
{{#*inline "z-recipient"}}<span class="compose_reply_button_recipient_label"></span>{{/inline}}
|
||||||
|
{{/tr}}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
<span class="new_message_button">
|
<span class="new_message_button">
|
||||||
<a class="drafts-link no-underline button small rounded compose_drafts_button" href="#drafts" title="{{t 'Drafts' }} (d)">
|
<a class="drafts-link no-underline button small rounded compose_drafts_button" href="#drafts" title="{{t 'Drafts' }} (d)">
|
||||||
{{t 'Drafts' }}
|
{{t 'Drafts' }}
|
||||||
</a>
|
</a>
|
||||||
<span class="alert-draft pull-left">{{t 'Saved as draft' }}</span>
|
<span class="alert-draft pull-left">{{t 'Saved as draft' }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="new_message_button">
|
<span class="new_message_button mobile_button_container">
|
||||||
<button type="button" class="button small rounded compose_mobile_button"
|
<button type="button" class="button small rounded compose_mobile_button"
|
||||||
id="left_bar_compose_mobile_button_big"
|
id="left_bar_compose_mobile_button_big"
|
||||||
title="{{t 'New message' }} (c)">
|
title="{{t 'New message' }} (c)">
|
||||||
<span>+</span>
|
<span>+</span>
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
<span class="new_message_button">
|
<span class="new_message_button stream_button_container">
|
||||||
<button type="button" class="button small rounded compose_stream_button"
|
<button type="button" class="button small rounded compose_stream_button"
|
||||||
id="left_bar_compose_stream_button_big"
|
id="left_bar_compose_stream_button_big"
|
||||||
title="{{t 'New topic' }} (c)">
|
title="{{t 'New topic' }} (c)">
|
||||||
@@ -26,7 +38,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
{{#unless embedded }}
|
{{#unless embedded }}
|
||||||
<span class="new_message_button">
|
<span class="new_message_button private_button_container">
|
||||||
<button type="button" class="button small rounded compose_private_button"
|
<button type="button" class="button small rounded compose_private_button"
|
||||||
id="left_bar_compose_private_button_big"
|
id="left_bar_compose_private_button_big"
|
||||||
title="{{t 'New private message' }} (x)">
|
title="{{t 'New private message' }} (x)">
|
||||||
@@ -34,13 +46,6 @@
|
|||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
<span class="new_message_button">
|
|
||||||
<button type="button" class="button small rounded compose_reply_button"
|
|
||||||
id="left_bar_compose_reply_button_big"
|
|
||||||
title="{{t 'Reply' }} (r)">
|
|
||||||
<span class="compose_reply_button_label">{{t 'Reply' }}</span>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="message_comp compose-content">
|
<div class="message_comp compose-content">
|
||||||
|
|||||||
Reference in New Issue
Block a user