FIX: makes chat user avatar show presence by default (#22490)
It's way more common to have presence enabled than disabled, so we should have been making it the default from start. This commit also changes the namespace of `<ChatUserAvatar />` into `<Chat::UserAvatar />` and refactors tests.
This commit is contained in:
parent
81a16a105e
commit
03e495186f
|
@ -7,7 +7,7 @@
|
|||
{{@channel.chatable.users.length}}
|
||||
</span>
|
||||
{{else}}
|
||||
<ChatUserAvatar @user={{@channel.chatable.users.firstObject}} />
|
||||
<Chat::UserAvatar @user={{@channel.chatable.users.firstObject}} />
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
>
|
||||
<div class="chat-reply">
|
||||
{{d-icon (if @message.editing "pencil-alt" "reply")}}
|
||||
<ChatUserAvatar @user={{@message.user}} />
|
||||
<Chat::UserAvatar @user={{@message.user}} />
|
||||
<span class="chat-reply__username">{{@message.user.username}}</span>
|
||||
<span class="chat-reply__excerpt">
|
||||
{{replace-emoji @message.excerpt}}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<div class="chat-message-actions">
|
||||
<div class="selected-message-container">
|
||||
<div class="selected-message">
|
||||
<ChatUserAvatar @user={{this.message.user}} />
|
||||
<Chat::UserAvatar @user={{this.message.user}} />
|
||||
<span
|
||||
{{on "touchstart" this.expandReply passive=true}}
|
||||
role="button"
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
{{#if @message.inReplyTo.chatWebhookEvent.emoji}}
|
||||
<ChatEmojiAvatar @emoji={{@message.inReplyTo.chatWebhookEvent.emoji}} />
|
||||
{{else}}
|
||||
<ChatUserAvatar @user={{@message.inReplyTo.user}} />
|
||||
<Chat::UserAvatar @user={{@message.inReplyTo.user}} />
|
||||
{{/if}}
|
||||
|
||||
<span class="chat-reply__excerpt">
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
>
|
||||
|
||||
<div class="chat-message-thread-indicator__last-reply-avatar">
|
||||
<ChatUserAvatar
|
||||
<Chat::UserAvatar
|
||||
@user={{@message.thread.preview.lastReplyUser}}
|
||||
@avatarSize="small"
|
||||
/>
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<div
|
||||
class="chat-user-avatar {{if (and this.isOnline @showPresence) 'is-online'}}"
|
||||
>
|
||||
<div
|
||||
role="button"
|
||||
class="chat-user-avatar-container clickable"
|
||||
data-user-card={{@user.username}}
|
||||
>
|
||||
{{avatar @user imageSize=this.avatarSize}}
|
||||
</div>
|
||||
</div>
|
|
@ -1,6 +1,6 @@
|
|||
{{#if @user}}
|
||||
<a href={{this.userPath}} data-user-card={{@user.username}}>
|
||||
<ChatUserAvatar @user={{@user}} @avatarSize="medium" />
|
||||
<Chat::UserAvatar @user={{@user}} @avatarSize="medium" />
|
||||
</a>
|
||||
<a href={{this.userPath}} data-user-card={{@user.username}}>
|
||||
<ChatUserDisplayName @user={{@user}} />
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<ChatUserAvatar @user={{@content.model}} @showPresence={{true}} />
|
||||
<Chat::UserAvatar @user={{@content.model}} />
|
||||
<ChatUserDisplayName @user={{@content.model}} />
|
||||
|
||||
{{#if (gt @content.tracking.unreadCount 0)}}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<ChatUserAvatar @user={{@selection.model}} @showPresence={{true}} />
|
||||
<Chat::UserAvatar @user={{@selection.model}} />
|
||||
|
||||
<span class="chat-message-creator__selection-item__username">
|
||||
{{@selection.model.username}}
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
{{#if @message.chatWebhookEvent.emoji}}
|
||||
<ChatEmojiAvatar @emoji={{@message.chatWebhookEvent.emoji}} />
|
||||
{{else}}
|
||||
<ChatUserAvatar
|
||||
@showPresence={{true}}
|
||||
@user={{@message.user}}
|
||||
@avatarSize="medium"
|
||||
/>
|
||||
<Chat::UserAvatar @user={{@message.user}} @avatarSize="medium" />
|
||||
{{/if}}
|
||||
</div>
|
|
@ -14,7 +14,7 @@
|
|||
>
|
||||
<div class="chat-thread-list-item__header">
|
||||
<div class="chat-thread-list-item__om-user-avatar">
|
||||
<ChatUserAvatar @user={{@thread.originalMessage.user}} />
|
||||
<Chat::UserAvatar @user={{@thread.originalMessage.user}} />
|
||||
</div>
|
||||
<div class="chat-thread-list-item__title overflow-ellipsis">
|
||||
{{replace-emoji this.title}}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="chat-thread-participants">
|
||||
<div class="chat-thread-participants__avatar-group">
|
||||
{{#each @thread.preview.participantUsers as |user|}}
|
||||
<ChatUserAvatar
|
||||
<Chat::UserAvatar
|
||||
@user={{user}}
|
||||
@avatarSize="tiny"
|
||||
@showPresence={{false}}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<div class="chat-user-avatar {{if this.isOnline 'is-online'}}">
|
||||
<div
|
||||
role="button"
|
||||
class="chat-user-avatar__container clickable"
|
||||
data-user-card={{@user.username}}
|
||||
>
|
||||
{{avatar @user imageSize=this.avatarSize}}
|
||||
</div>
|
||||
</div>
|
|
@ -8,12 +8,19 @@ export default class ChatUserAvatar extends Component {
|
|||
return this.args.avatarSize || "tiny";
|
||||
}
|
||||
|
||||
get showPresence() {
|
||||
return this.args.showPresence ?? true;
|
||||
}
|
||||
|
||||
get isOnline() {
|
||||
const users = (this.args.chat || this.chat).presenceChannel?.users;
|
||||
|
||||
return (
|
||||
!!users?.findBy("id", this.args.user?.id) ||
|
||||
!!users?.findBy("username", this.args.user?.username)
|
||||
this.showPresence &&
|
||||
!!users?.find(
|
||||
({ id, username }) =>
|
||||
this.args.user?.id === id || this.args.user?.username === username
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -186,60 +186,6 @@ html.ios-device.keyboard-visible body #main-outlet .full-page-chat {
|
|||
}
|
||||
}
|
||||
|
||||
.chat-user-avatar {
|
||||
@include unselectable;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.chat-message-container:not(.has-reply) & {
|
||||
width: var(--message-left-width);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&.is-online {
|
||||
.chat-user-avatar-container .avatar {
|
||||
box-shadow: 0px 0px 0px 1px var(--success);
|
||||
border: 1px solid var(--secondary);
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-user-avatar-container {
|
||||
position: relative;
|
||||
padding: 1px; // for is-online box-shadow effect, preventing cutoff
|
||||
|
||||
.avatar {
|
||||
padding: 1px; // for is-online box-shadow effect, preventing shift
|
||||
}
|
||||
|
||||
.chat-user-presence-flair {
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
background-color: var(--success);
|
||||
border: 1px solid var(--secondary);
|
||||
border-radius: 50%;
|
||||
|
||||
.chat-message & {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.chat-channel-title & {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
right: -1px;
|
||||
bottom: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat-channel-title & {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.topic-title-chat-icon {
|
||||
display: inline-block;
|
||||
* {
|
||||
|
|
|
@ -121,7 +121,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.chat-message-avatar .chat-user-avatar .chat-user-avatar-container .avatar,
|
||||
.chat-message-avatar .chat-user-avatar .chat-user-avatar__container .avatar,
|
||||
.chat-emoji-avatar .chat-emoji-avatar-container {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
|
||||
.chat-user-avatar-container {
|
||||
.chat-user-avatar__container {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
|||
&__avatar-group {
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
|
||||
.chat-user-avatar {
|
||||
&:not(:last-child) {
|
||||
margin-right: -10px;
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
.chat-user-avatar {
|
||||
@include unselectable;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.chat-message-container:not(.has-reply) & {
|
||||
width: var(--message-left-width);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&.is-online {
|
||||
.chat-user-avatar__container .avatar {
|
||||
box-shadow: 0px 0px 0px 1px var(--success);
|
||||
border: 1px solid var(--secondary);
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__container {
|
||||
position: relative;
|
||||
padding: 1px; // for is-online box-shadow effect, preventing cutoff
|
||||
|
||||
.avatar {
|
||||
padding: 1px; // for is-online box-shadow effect, preventing shift
|
||||
}
|
||||
|
||||
.chat-user-presence-flair {
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
background-color: var(--success);
|
||||
border: 1px solid var(--secondary);
|
||||
border-radius: 50%;
|
||||
|
||||
.chat-message & {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.chat-channel-title & {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
right: -1px;
|
||||
bottom: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat-channel-title & {
|
||||
width: auto;
|
||||
}
|
||||
}
|
|
@ -59,3 +59,4 @@
|
|||
@import "chat-message-error";
|
||||
@import "chat-new-message-modal";
|
||||
@import "chat-message-creator";
|
||||
@import "chat-user-avatar";
|
||||
|
|
|
@ -33,7 +33,7 @@ module PageObjects
|
|||
|
||||
def has_participant?(user)
|
||||
find(@context).has_css?(
|
||||
".chat-thread-participants__avatar-group .chat-user-avatar .chat-user-avatar-container[data-user-card=\"#{user.username}\"] img",
|
||||
".chat-thread-participants__avatar-group .chat-user-avatar .chat-user-avatar__container[data-user-card=\"#{user.username}\"] img",
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ module PageObjects
|
|||
end
|
||||
|
||||
def avatar_selector(user)
|
||||
".chat-thread-list-item__om-user-avatar .chat-user-avatar .chat-user-avatar-container[data-user-card=\"#{user.username}\"] img"
|
||||
".chat-thread-list-item__om-user-avatar .chat-user-avatar .chat-user-avatar__container[data-user-card=\"#{user.username}\"] img"
|
||||
end
|
||||
|
||||
def last_reply_datetime_selector(last_reply)
|
||||
|
|
|
@ -71,7 +71,7 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) {
|
|||
const user = this.channel.chatable.users[0];
|
||||
|
||||
assert.true(
|
||||
exists(`.chat-user-avatar-container .avatar[title="${user.username}"]`)
|
||||
exists(`.chat-user-avatar__container .avatar[title="${user.username}"]`)
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
|
|
|
@ -1,50 +1,55 @@
|
|||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||
import { exists } from "discourse/tests/helpers/qunit-helpers";
|
||||
import hbs from "htmlbars-inline-precompile";
|
||||
import { module, test } from "qunit";
|
||||
import { render } from "@ember/test-helpers";
|
||||
import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
|
||||
|
||||
const user = {
|
||||
id: 1,
|
||||
username: "markvanlan",
|
||||
name: null,
|
||||
avatar_template: "/letter_avatar_proxy/v4/letter/m/48db29/{size}.png",
|
||||
};
|
||||
function containerSelector(user, options = {}) {
|
||||
let onlineSelector = ":not(.is-online)";
|
||||
if (options.online) {
|
||||
onlineSelector = ".is-online";
|
||||
}
|
||||
|
||||
module("Discourse Chat | Component | chat-user-avatar", function (hooks) {
|
||||
return `.chat-user-avatar${onlineSelector} .chat-user-avatar__container[data-user-card=${user.username}] .avatar[title=${user.username}]`;
|
||||
}
|
||||
|
||||
module("Discourse Chat | Component | <Chat::UserAvatar />", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test("user is not online", async function (assert) {
|
||||
this.set("user", user);
|
||||
this.set("chat", { presenceChannel: { users: [] } });
|
||||
this.user = fabricators.user();
|
||||
this.chat = { presenceChannel: { users: [] } };
|
||||
|
||||
await render(
|
||||
hbs`<ChatUserAvatar @chat={{this.chat}} @user={{this.user}} />`
|
||||
hbs`<Chat::UserAvatar @chat={{this.chat}} @user={{this.user}} />`
|
||||
);
|
||||
|
||||
assert.true(
|
||||
exists(
|
||||
`.chat-user-avatar .chat-user-avatar-container[data-user-card=${user.username}] .avatar[title=${user.username}]`
|
||||
)
|
||||
);
|
||||
assert.false(exists(".chat-user-avatar.is-online"));
|
||||
assert.dom(containerSelector(this.user, { online: false })).exists();
|
||||
});
|
||||
|
||||
test("user is online", async function (assert) {
|
||||
this.set("user", user);
|
||||
this.set("chat", {
|
||||
presenceChannel: { users: [{ id: user.id }] },
|
||||
});
|
||||
this.user = fabricators.user();
|
||||
this.chat = {
|
||||
presenceChannel: { users: [{ id: this.user.id }] },
|
||||
};
|
||||
|
||||
await render(
|
||||
hbs`<ChatUserAvatar @showPresence={{true}} @chat={{this.chat}} @user={{this.user}} />`
|
||||
hbs`<Chat::UserAvatar @chat={{this.chat}} @user={{this.user}} />`
|
||||
);
|
||||
|
||||
assert.true(
|
||||
exists(
|
||||
`.chat-user-avatar .chat-user-avatar-container[data-user-card=${user.username}] .avatar[title=${user.username}]`
|
||||
)
|
||||
assert.dom(containerSelector(this.user, { online: true })).exists();
|
||||
});
|
||||
|
||||
test("showPresence=false", async function (assert) {
|
||||
this.user = fabricators.user();
|
||||
this.chat = {
|
||||
presenceChannel: { users: [{ id: this.user.id }] },
|
||||
};
|
||||
|
||||
await render(
|
||||
hbs`<Chat::UserAvatar @showPresence={{false}} @chat={{this.chat}} @user={{this.user}} />`
|
||||
);
|
||||
assert.true(exists(".chat-user-avatar.is-online"));
|
||||
|
||||
assert.dom(containerSelector(this.user, { online: false })).exists();
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue