buddy_list: Add option to view avatar in buddy list.

Fixes #19999.

This change adds an option to show users' avatar and
status in the buddy list. Previous options are still
available in the settings menu.
This commit is contained in:
evykassirer 2024-10-23 23:10:56 -07:00 committed by Tim Abbott
parent 774f230074
commit 94368dcf2b
12 changed files with 103 additions and 9 deletions

View File

@ -8,6 +8,7 @@ import * as bot_data from "./bot_data";
import * as demo_organizations_ui from "./demo_organizations_ui"; import * as demo_organizations_ui from "./demo_organizations_ui";
import {$t, get_language_name, language_list} from "./i18n"; import {$t, get_language_name, language_list} from "./i18n";
import {page_params} from "./page_params"; import {page_params} from "./page_params";
import * as people from "./people";
import {realm_user_settings_defaults} from "./realm_user_settings_defaults"; import {realm_user_settings_defaults} from "./realm_user_settings_defaults";
import * as settings from "./settings"; import * as settings from "./settings";
import * as settings_bots from "./settings_bots"; import * as settings_bots from "./settings_bots";
@ -109,6 +110,7 @@ export function build_page() {
const options = { const options = {
custom_profile_field_types: realm.custom_profile_field_types, custom_profile_field_types: realm.custom_profile_field_types,
full_name: current_user.full_name, full_name: current_user.full_name,
profile_picture: people.small_avatar_url_for_person(current_user),
realm_name: realm.realm_name, realm_name: realm.realm_name,
realm_org_type: realm.realm_org_type, realm_org_type: realm.realm_org_type,
realm_available_video_chat_providers: realm.realm_available_video_chat_providers, realm_available_video_chat_providers: realm.realm_available_video_chat_providers,

View File

@ -172,6 +172,7 @@ export type BuddyUserInfo = {
href: string; href: string;
name: string; name: string;
user_id: number; user_id: number;
profile_picture: string;
status_emoji_info: user_status.UserStatusEmojiInfo | undefined; status_emoji_info: user_status.UserStatusEmojiInfo | undefined;
is_current_user: boolean; is_current_user: boolean;
num_unread: number; num_unread: number;
@ -204,6 +205,7 @@ export function info_for(user_id: number): BuddyUserInfo {
name: person.full_name, name: person.full_name,
user_id, user_id,
status_emoji_info, status_emoji_info,
profile_picture: people.small_avatar_url_for_person(person),
is_current_user: people.is_my_user_id(user_id), is_current_user: people.is_my_user_id(user_id),
num_unread: get_num_unread(user_id), num_unread: get_num_unread(user_id),
user_circle_class, user_circle_class,

View File

@ -93,6 +93,9 @@ export function build_page() {
const rendered_settings_tab = render_settings_tab({ const rendered_settings_tab = render_settings_tab({
full_name: people.my_full_name(), full_name: people.my_full_name(),
profile_picture: people.small_avatar_url_for_person(
people.get_by_user_id(people.my_current_user_id()),
),
date_joined_text: get_parsed_date_of_joining(), date_joined_text: get_parsed_date_of_joining(),
current_user, current_user,
page_params, page_params,

View File

@ -77,11 +77,10 @@ export const user_list_style_values = {
code: 2, code: 2,
description: $t({defaultMessage: "Show status text"}), description: $t({defaultMessage: "Show status text"}),
}, },
// The `with_avatar` design in still in discussion. with_avatar: {
// with_avatar: { code: 3,
// code: 3, description: $t({defaultMessage: "Show avatar"}),
// description: $t({defaultMessage: "Show status text and avatar"}), },
// },
}; };
export const web_animate_image_previews_values = { export const web_animate_image_previews_values = {

View File

@ -276,6 +276,7 @@
the smaller line-height. */ the smaller line-height. */
--line-height-sidebar-row-prominent: 1.7142em; /* 24px / 14px em */ --line-height-sidebar-row-prominent: 1.7142em; /* 24px / 14px em */
--line-height-sidebar-row: 1.5714em; /* 22px / 14px em */ --line-height-sidebar-row: 1.5714em; /* 22px / 14px em */
--line-height-sidebar-row-with-avatars: 1.2857em; /* 18px / 14px em */
/* Right sidebar */ /* Right sidebar */
--right-sidebar-padding-right: 8px; --right-sidebar-padding-right: 8px;
@ -283,6 +284,8 @@
space created by the padding-left on .right-sidebar, space created by the padding-left on .right-sidebar,
which separates the right sidebar from the message area. */ which separates the right sidebar from the message area. */
--right-sidebar-padding-left: 2px; --right-sidebar-padding-left: 2px;
--right-sidebar-avatar-width: 2em;
--right-sidebar-avatar-height: var(--right-sidebar-avatar-width);
/* Tippy popover related values */ /* Tippy popover related values */
--navbar-popover-menu-min-width: 230px; --navbar-popover-menu-min-width: 230px;

View File

@ -143,6 +143,10 @@ $user_status_emoji_width: 24px;
&.highlighted_user { &.highlighted_user {
background-color: var(--color-buddy-list-highlighted-user); background-color: var(--color-buddy-list-highlighted-user);
box-shadow: inset 0 0 0 1px var(--color-shadow-sidebar-row-hover); box-shadow: inset 0 0 0 1px var(--color-shadow-sidebar-row-hover);
.user_circle {
outline: 1px solid var(--color-buddy-list-highlighted-user);
}
} }
} }
@ -161,6 +165,15 @@ $user_status_emoji_width: 24px;
} }
} }
.user_sidebar_entry.with_avatar .user_circle {
display: inline-block;
position: absolute;
width: 0.4em;
height: 0.4em;
top: 1.7em;
left: 1.7em;
}
.empty-list-message { .empty-list-message {
font-style: italic; font-style: italic;
color: var(--color-text-empty-list-message); color: var(--color-text-empty-list-message);
@ -241,6 +254,13 @@ $user_status_emoji_width: 24px;
align-items: baseline; align-items: baseline;
} }
.user_sidebar_entry.with_avatar .selectable_sidebar_block {
grid-template:
"row-content markers-and-controls" var(--line-height-sidebar-row-with-avatars)
"row-content ." auto / minmax(0, 1fr)
minmax(0, auto);
}
.user-presence-link { .user-presence-link {
grid-area: row-content; grid-area: row-content;
@ -251,6 +271,26 @@ $user_status_emoji_width: 24px;
} }
} }
.information-settings .profile-with-avatar,
.user_sidebar_entry.with_avatar .user-presence-link {
line-height: var(--line-height-sidebar-row-with-avatars);
display: grid;
grid-template: "avatar row-content" var(--right-sidebar-avatar-width) / auto minmax(
0,
1fr
);
justify-content: flex-start;
align-items: center;
}
.information-settings .profile-with-avatar {
margin: 5px 0;
}
.user_sidebar_entry.with_avatar .user-presence-link {
margin: 3px;
}
.my_user_status { .my_user_status {
opacity: 0.5; opacity: 0.5;
white-space: nowrap; white-space: nowrap;

View File

@ -6,6 +6,10 @@
border: 1px solid; border: 1px solid;
} }
.user_sidebar_entry.with_avatar .user_circle {
outline: 1px solid var(--color-background);
}
.user_circle_green { .user_circle_green {
background-color: var(--color-user-circle-active); background-color: var(--color-user-circle-active);
border-color: var(--color-user-circle-active); border-color: var(--color-user-circle-active);

View File

@ -999,10 +999,10 @@ div.focused-message-list {
background-color: transparent; background-color: transparent;
} }
.information-settings .user-profile-picture,
.user_sidebar_entry.with_avatar .user-profile-picture,
.inline_profile_picture { .inline_profile_picture {
display: inline-block; display: inline-block;
width: var(--message-box-avatar-width);
height: var(--message-box-avatar-height);
/* Don't inherit the line-height from message-avatar; /* Don't inherit the line-height from message-avatar;
this preserves the dimensions and rounded corners this preserves the dimensions and rounded corners
on the image itself. */ on the image itself. */
@ -1017,6 +1017,17 @@ div.focused-message-list {
} }
} }
.inline_profile_picture {
width: var(--message-box-avatar-width);
height: var(--message-box-avatar-height);
}
.information-settings .user-profile-picture,
.user_sidebar_entry.with_avatar .user-profile-picture {
width: var(--right-sidebar-avatar-width);
height: var(--right-sidebar-avatar-height);
}
.home-error-bar { .home-error-bar {
margin-top: 5px; margin-top: 5px;
display: none; display: none;

View File

@ -1,6 +1,6 @@
<li data-user-id="{{user_id}}" class="user_sidebar_entry {{#if is_current_user}}user_sidebar_entry_me {{/if}} narrow-filter {{#if faded}} user-fade {{/if}}"> <li data-user-id="{{user_id}}" class="user_sidebar_entry {{#if user_list_style.WITH_AVATAR}}with_avatar{{/if}} {{#if is_current_user}}user_sidebar_entry_me {{/if}} narrow-filter {{#if faded}} user-fade {{/if}}">
<div class="selectable_sidebar_block"> <div class="selectable_sidebar_block">
<span class="{{user_circle_class}} user_circle"></span> {{#unless user_list_style.WITH_AVATAR}}<span class="{{user_circle_class}} user_circle"></span>{{/unless}}
<a class="user-presence-link" <a class="user-presence-link"
href="{{href}}" href="{{href}}"
data-user-id="{{user_id}}" data-user-id="{{user_id}}"
@ -13,6 +13,18 @@
</div> </div>
<span class="status-text">{{status_text}}</span> <span class="status-text">{{status_text}}</span>
</div> </div>
{{else if user_list_style.WITH_AVATAR}}
<div class="user-profile-picture">
<img loading="lazy" src="{{profile_picture}}"/>
<span class="{{user_circle_class}} user_circle"></span>
</div>
<div class="user-name-and-status-wrapper">
<div class="user-name-and-status-emoji">
{{> user_full_name}}
{{> status_emoji status_emoji_info}}
</div>
<span class="status-text">{{status_text}}</span>
</div>
{{else}} {{else}}
<div class="user-name-and-status-emoji"> <div class="user-name-and-status-emoji">
{{> user_full_name}} {{> user_full_name}}

View File

@ -29,6 +29,20 @@
<span class="status-text">{{t "Working remotely" }}</span> <span class="status-text">{{t "Working remotely" }}</span>
</div> </div>
{{/if}} {{/if}}
{{#if (eq this.code 3)}}
<div class="profile-with-avatar">
<div class="user-profile-picture">
<img src="{{../profile_picture}}"/>
</div>
<div class="user-name-and-status-wrapper">
<div class="user-name-and-status-emoji">
<span class="user-name">{{../full_name}}</span>
{{> ../status_emoji emoji_code="1f3e0"}}
</div>
<span class="status-text">{{t "Working remotely" }}</span>
</div>
</div>
{{/if}}
</span> </span>
</label> </label>
{{/each}} {{/each}}

View File

@ -501,6 +501,7 @@ test("insert_one_user_into_empty_list", ({override, mock_template}) => {
user_id: 1, user_id: 1,
is_current_user: false, is_current_user: false,
num_unread: 0, num_unread: 0,
profile_picture: "/avatar/1",
user_circle_class: "user_circle_green", user_circle_class: "user_circle_green",
status_emoji_info: undefined, status_emoji_info: undefined,
status_text: undefined, status_text: undefined,

View File

@ -604,6 +604,7 @@ test("get_items_for_users", ({override}) => {
is_current_user: true, is_current_user: true,
name: "Human Myself", name: "Human Myself",
num_unread: 0, num_unread: 0,
profile_picture: "/avatar/1001",
status_emoji_info, status_emoji_info,
status_text: undefined, status_text: undefined,
user_circle_class: "user_circle_green", user_circle_class: "user_circle_green",
@ -616,6 +617,7 @@ test("get_items_for_users", ({override}) => {
is_current_user: false, is_current_user: false,
name: "Alice Smith", name: "Alice Smith",
num_unread: 0, num_unread: 0,
profile_picture: "/avatar/1002",
status_emoji_info, status_emoji_info,
status_text: undefined, status_text: undefined,
user_circle_class: "user_circle_empty", user_circle_class: "user_circle_empty",
@ -628,6 +630,7 @@ test("get_items_for_users", ({override}) => {
is_current_user: false, is_current_user: false,
name: "Fred Flintstone", name: "Fred Flintstone",
num_unread: 0, num_unread: 0,
profile_picture: "/avatar/1003",
status_emoji_info, status_emoji_info,
status_text: undefined, status_text: undefined,
user_circle_class: "user_circle_empty", user_circle_class: "user_circle_empty",