compose: Add user presence circles in mention and pm typeahead.

This commit addresses the problem of user's status visibility to
some extent. It adds presence circles, like we have in buddy_list to the
typeahead suggestions that are given for mentioning users in messages.

Tweaked by tabbott to adjust vertical alignment of group mentions as well.

Testing for the changes is done manually in the developement server,
and also by updating frontend tests to address these changes.

Fixes: #17138
This commit is contained in:
m-e-l-u-h-a-n 2021-02-26 13:54:04 +05:30 committed by Tim Abbott
parent 7def3e7832
commit f4a111e314
5 changed files with 42 additions and 4 deletions

View File

@ -50,6 +50,10 @@ rewiremock.enable();
const emoji = zrequire("emoji", "shared/js/emoji");
const typeahead = zrequire("typeahead", "shared/js/typeahead");
const compose_state = zrequire("compose_state");
zrequire("user_status");
zrequire("presence");
zrequire("buddy_data");
zrequire("pm_conversations");
zrequire("templates");
const typeahead_helper = zrequire("typeahead_helper");
const people = zrequire("people");
@ -695,17 +699,17 @@ run_test("initialize", () => {
// corresponding parts in bold.
options.query = "oth";
actual_value = options.highlighter(othello);
expected_value = ` <img class="typeahead-image" src="/avatar/${othello.user_id}&amp;s&#x3D;50" />\n<strong>Othello, the Moor of Venice</strong>`;
expected_value = ` <span class="user_circle_empty user_circle"></span>\n <img class="typeahead-image" src="/avatar/${othello.user_id}&amp;s&#x3D;50" />\n<strong>Othello, the Moor of Venice</strong>`;
assert.equal(actual_value, expected_value);
options.query = "Lear";
actual_value = options.highlighter(cordelia);
expected_value = ` <img class="typeahead-image" src="/avatar/${cordelia.user_id}&amp;s&#x3D;50" />\n<strong>Cordelia Lear</strong>`;
expected_value = ` <span class="user_circle_empty user_circle"></span>\n <img class="typeahead-image" src="/avatar/${cordelia.user_id}&amp;s&#x3D;50" />\n<strong>Cordelia Lear</strong>`;
assert.equal(actual_value, expected_value);
options.query = "othello@zulip.com, co";
actual_value = options.highlighter(cordelia);
expected_value = ` <img class="typeahead-image" src="/avatar/${cordelia.user_id}&amp;s&#x3D;50" />\n<strong>Cordelia Lear</strong>`;
expected_value = ` <span class="user_circle_empty user_circle"></span>\n <img class="typeahead-image" src="/avatar/${cordelia.user_id}&amp;s&#x3D;50" />\n<strong>Cordelia Lear</strong>`;
assert.equal(actual_value, expected_value);
function matcher(query, person) {
@ -871,7 +875,7 @@ run_test("initialize", () => {
// content_highlighter.
fake_this = {completing: "mention", token: "othello"};
actual_value = options.highlighter.call(fake_this, othello);
expected_value = ` <img class="typeahead-image" src="/avatar/${othello.user_id}&amp;s&#x3D;50" />\n<strong>Othello, the Moor of Venice</strong>`;
expected_value = ` <span class="user_circle_empty user_circle"></span>\n <img class="typeahead-image" src="/avatar/${othello.user_id}&amp;s&#x3D;50" />\n<strong>Othello, the Moor of Venice</strong>`;
assert.equal(actual_value, expected_value);
fake_this = {completing: "mention", token: "hamletcharacters"};

View File

@ -18,6 +18,11 @@ const recent_senders = zrequire("recent_senders");
const peer_data = zrequire("peer_data");
const people = zrequire("people");
const stream_data = zrequire("stream_data");
zrequire("narrow");
zrequire("user_status");
zrequire("presence");
zrequire("buddy_data");
zrequire("hash_util");
const emoji = zrequire("emoji", "shared/js/emoji");
const pygments_data = zrequire("pygments_data", "generated/pygments_data.json");

View File

@ -6,6 +6,7 @@ import * as emoji from "../shared/js/emoji";
import * as typeahead from "../shared/js/typeahead";
import render_typeahead_list_item from "../templates/typeahead_list_item.hbs";
import * as buddy_data from "./buddy_data";
import * as people from "./people";
import * as pm_conversations from "./pm_conversations";
import * as recent_senders from "./recent_senders";
@ -75,9 +76,11 @@ export function render_typeahead_item(args) {
const rendered = {persons: new Map(), streams: new Map(), user_groups: new Map()};
export function render_person(person) {
const user_circle_class = buddy_data.get_user_circle_class(person.user_id);
if (person.special_item_text) {
return render_typeahead_item({
primary: person.special_item_text,
user_circle_class,
is_person: true,
});
}
@ -89,6 +92,7 @@ export function render_person(person) {
const typeahead_arguments = {
primary: person.full_name,
img_src: avatar_url,
user_circle_class,
is_person: true,
};
typeahead_arguments.secondary = settings_data.email_for_user_settings(person);

View File

@ -620,6 +620,19 @@ strong {
background-repeat: repeat-x;
filter: progid:dximagetransform.microsoft.gradient(startcolorstr='hsla(328, 100%, 50%, 0.8)', endcolorstr='hsla(332, 100%, 50%, 0.7)', gradienttype=0);
}
/* styles defined for user_circle here only deal with positioning of user_presence_circle
in typeahead list in order to ensure they are renderred correctly in in all screen sizes.
Most of the style rules related to color, gradient etc. which are generally common throughout
the app are defined in user_circles.css and are not overridden here. */
.user_circle {
width: 8px;
height: 8px;
margin: 0 5px 0 -6px;
position: relative;
top: 6px;
right: 7px;
display: inline-block;
}
}
}
@ -635,6 +648,10 @@ strong {
background-repeat: repeat-x;
outline: 0;
filter: progid:dximagetransform.microsoft.gradient(startcolorstr='hsla(328, 100%, 50%, 0.8)', endcolorstr='hsla(332, 100%, 50%, 0.7)', gradienttype=0);
.user_circle_empty {
border-color: hsl(0, 0%, 25%);
}
}
.active > a:hover {
@ -2035,6 +2052,11 @@ div.focused_table {
/* For FontAwesome icons used in place of images for some users. */
font-size: 19px;
text-align: center;
&.fa-group {
margin-left: 9px;
top: 3px;
}
}
nav {

View File

@ -7,6 +7,9 @@
&nbsp;&nbsp;
{{else}}
{{#if is_person}}
{{#if user_circle_class}}
<span class="{{user_circle_class}} user_circle"></span>
{{/if}}
{{#if has_image}}
<img class="typeahead-image" src="{{ img_src }}" />
{{else}}