mirror of https://github.com/zulip/zulip.git
recent_topics: Add avatars of recent senders to topic.
This commit is contained in:
parent
bdaf4e1079
commit
bc7136590a
|
@ -598,6 +598,26 @@ run_test('message_methods', () => {
|
|||
|
||||
assert.equal(people.small_avatar_url_for_person(maria),
|
||||
'https://secure.gravatar.com/avatar/md5-athens@example.com?d=identicon&s=50');
|
||||
|
||||
assert.deepEqual(people.sender_info_with_small_avatar_urls_for_sender_ids([30]), [
|
||||
{
|
||||
avatar_url_small: 'https://secure.gravatar.com/avatar/md5-me@example.com?d=identicon&s=50',
|
||||
email: 'me@example.com',
|
||||
full_name: 'Me the Third',
|
||||
is_admin: false,
|
||||
is_bot: false,
|
||||
is_guest: false,
|
||||
profile_data: {
|
||||
3: {
|
||||
rendered_value: '<p>Field value</p>',
|
||||
value: 'Field value',
|
||||
},
|
||||
},
|
||||
timezone: 'US/Pacific',
|
||||
user_id: 30,
|
||||
},
|
||||
]);
|
||||
|
||||
let message = {
|
||||
type: 'private',
|
||||
display_recipient: [
|
||||
|
|
|
@ -13,6 +13,9 @@ set_global('people', {
|
|||
is_my_user_id: function (id) {
|
||||
return id === 1;
|
||||
},
|
||||
sender_info_with_small_avatar_urls_for_sender_ids: (ids) => {
|
||||
return ids;
|
||||
},
|
||||
});
|
||||
set_global('XDate', zrequire('XDate', 'xdate'));
|
||||
set_global('timerender', {
|
||||
|
@ -33,6 +36,9 @@ set_global('hash_util', {
|
|||
return "https://www.example.com";
|
||||
},
|
||||
});
|
||||
set_global('recent_senders', {
|
||||
get_topic_recent_senders: () => { return [1, 2]; },
|
||||
});
|
||||
|
||||
// Custom Data
|
||||
|
||||
|
@ -195,6 +201,8 @@ run_test("test_recent_topics_launch", () => {
|
|||
stream_url: 'https://www.example.com',
|
||||
topic_url: 'https://www.example.com',
|
||||
hidden: true,
|
||||
senders: [1, 2],
|
||||
count_senders: 0,
|
||||
},
|
||||
{
|
||||
stream_id: 1,
|
||||
|
@ -205,6 +213,8 @@ run_test("test_recent_topics_launch", () => {
|
|||
stream_url: 'https://www.example.com',
|
||||
topic_url: 'https://www.example.com',
|
||||
hidden: false,
|
||||
senders: [1, 2],
|
||||
count_senders: 0,
|
||||
},
|
||||
{
|
||||
stream_id: 1,
|
||||
|
@ -215,6 +225,8 @@ run_test("test_recent_topics_launch", () => {
|
|||
stream_url: 'https://www.example.com',
|
||||
topic_url: 'https://www.example.com',
|
||||
hidden: false,
|
||||
senders: [1, 2],
|
||||
count_senders: 0,
|
||||
},
|
||||
{
|
||||
stream_id: 1,
|
||||
|
@ -225,6 +237,8 @@ run_test("test_recent_topics_launch", () => {
|
|||
stream_url: 'https://www.example.com',
|
||||
topic_url: 'https://www.example.com',
|
||||
hidden: false,
|
||||
senders: [1, 2],
|
||||
count_senders: 0,
|
||||
},
|
||||
{
|
||||
stream_id: 1,
|
||||
|
@ -235,6 +249,8 @@ run_test("test_recent_topics_launch", () => {
|
|||
stream_url: 'https://www.example.com',
|
||||
topic_url: 'https://www.example.com',
|
||||
hidden: false,
|
||||
senders: [1, 2],
|
||||
count_senders: 0,
|
||||
},
|
||||
{
|
||||
stream_id: 1,
|
||||
|
@ -245,6 +261,8 @@ run_test("test_recent_topics_launch", () => {
|
|||
stream_url: 'https://www.example.com',
|
||||
topic_url: 'https://www.example.com',
|
||||
hidden: false,
|
||||
senders: [1, 2],
|
||||
count_senders: 0,
|
||||
},
|
||||
{
|
||||
stream_id: 1,
|
||||
|
@ -255,6 +273,8 @@ run_test("test_recent_topics_launch", () => {
|
|||
stream_url: 'https://www.example.com',
|
||||
topic_url: 'https://www.example.com',
|
||||
hidden: false,
|
||||
senders: [1, 2],
|
||||
count_senders: 0,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
@ -605,6 +605,16 @@ exports.small_avatar_url_for_person = function (person) {
|
|||
return gravatar_url_for_email(person.email);
|
||||
};
|
||||
|
||||
exports.sender_info_with_small_avatar_urls_for_sender_ids = function (sender_ids) {
|
||||
const senders_info = [];
|
||||
for (const id of sender_ids) {
|
||||
const sender = {...exports.get_by_user_id(id)};
|
||||
sender.avatar_url_small = exports.small_avatar_url_for_person(sender);
|
||||
senders_info.push(sender);
|
||||
}
|
||||
return senders_info;
|
||||
};
|
||||
|
||||
exports.small_avatar_url = function (message) {
|
||||
// Try to call this function in all places where we need 25px
|
||||
// avatar images, so that the browser can help
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
const render_recent_topics_body = require('../templates/recent_topics_table.hbs');
|
||||
const render_recent_topic_row = require('../templates/recent_topic_row.hbs');
|
||||
const topics = new Map(); // Key is stream-id:topic.
|
||||
// Sets the number of avatars to display.
|
||||
// Rest of the avatars, if present, are displayed as {+x}
|
||||
const MAX_AVATAR = 4;
|
||||
|
||||
exports.process_messages = function (messages) {
|
||||
// Since a complete re-render is expensive, we
|
||||
|
@ -77,6 +80,12 @@ function format_topic(topic_data) {
|
|||
const last_msg_time = timerender.last_seen_status_from_date(time);
|
||||
const unread_count = unread.unread_topic_counter.get(stream_id, topic);
|
||||
const hidden = muting.is_topic_muted(stream_id, topic);
|
||||
|
||||
// Display in most recent sender first order
|
||||
const all_senders = recent_senders.get_topic_recent_senders(stream_id, topic);
|
||||
const senders = all_senders.slice(-MAX_AVATAR);
|
||||
const senders_info = people.sender_info_with_small_avatar_urls_for_sender_ids(senders);
|
||||
|
||||
return {
|
||||
stream_id: stream_id,
|
||||
stream: stream,
|
||||
|
@ -86,6 +95,8 @@ function format_topic(topic_data) {
|
|||
stream_url: hash_util.by_stream_uri(stream_id),
|
||||
topic_url: hash_util.by_stream_topic_uri(stream_id, topic),
|
||||
hidden: hidden,
|
||||
senders: senders_info,
|
||||
count_senders: Math.max(0, all_senders.length - MAX_AVATAR),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -69,5 +69,44 @@
|
|||
// is set to header's width.
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.recent_avatars {
|
||||
display: inline-flex; /* Causes LI items to display in row. */
|
||||
list-style-type: none;
|
||||
margin: auto; /* Centers vertically / horizontally in flex container. */
|
||||
height: 15px !important;
|
||||
|
||||
/*
|
||||
By using the row-reverse layout, the visual ordering will be opposite of
|
||||
the DOM ordering. This will allows us to stack the items in the opposite
|
||||
direction of the natural stacking order without having to mess with the
|
||||
zIndex value. The MAJOR DOWNSIDE is that the HTML itself now reads
|
||||
backwards, which super janky.
|
||||
*/
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.recent_avatars_item {
|
||||
height: 18px;
|
||||
margin: 0px 0px 0px 0px;
|
||||
padding: 0px 0px 0px 0px;
|
||||
position: relative;
|
||||
min-width: 18px;
|
||||
}
|
||||
|
||||
.recent_avatars_img,
|
||||
.recent_avatars_others {
|
||||
border: 1px solid hsl(221.1, 23.5%, 15.9%);
|
||||
border-left: 0 !important;
|
||||
border-radius: 6px;
|
||||
color: hsl(0, 0%, 100%);
|
||||
display: block;
|
||||
height: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.recent_avatars_others {
|
||||
background-color: hsl(205.2, 76.5%, 50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,18 @@
|
|||
<i class="fa fa-check-circle on_hover_topic_read recipient_bar_icon" data-stream-id="{{stream_id}}" data-topic-name="{{topic}}" title="{{t 'Mark as read' }}" role="button" tabindex="0" aria-label="{{t 'Mark as read' }}"></i>
|
||||
</td>
|
||||
<td class='recent_topic_users'>
|
||||
<ul class="recent_avatars">
|
||||
{{#if count_senders}}
|
||||
<li class="recent_avatars_item">
|
||||
<span class="recent_avatars_others">+{{count_senders}}</span>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#each senders}}
|
||||
<li class="recent_avatars_item" title="{{this.full_name}}">
|
||||
<img src="{{this.avatar_url_small}}" class="recent_avatars_img" />
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</td>
|
||||
<td class="recent_topic_timestamp">
|
||||
{{ last_msg_time }}
|
||||
|
|
Loading…
Reference in New Issue