diff options
author | Maksim Sukharev <antreesy.web@gmail.com> | 2023-09-27 16:25:50 +0200 |
---|---|---|
committer | Maksim Sukharev <antreesy.web@gmail.com> | 2023-09-29 10:56:52 +0200 |
commit | cc6a7c564e35b8844bdaa94c2c9fcf96bf95b4dd (patch) | |
tree | 3ac5e5cb76303bfb0a1857317cba6682fa537bdb | |
parent | 450a9270baa5af3e03df15668444c08b2f5dc5b2 (diff) |
replace single-used AuthorAvatar component with AvatarWrapper
Signed-off-by: Maksim Sukharev <antreesy.web@gmail.com>
4 files changed, 72 insertions, 148 deletions
diff --git a/src/components/AvatarWrapper/AvatarWrapper.vue b/src/components/AvatarWrapper/AvatarWrapper.vue index 6f9957f78..196be555b 100644 --- a/src/components/AvatarWrapper/AvatarWrapper.vue +++ b/src/components/AvatarWrapper/AvatarWrapper.vue @@ -2,8 +2,9 @@ - @copyright Copyright (c) 2020 Marco Ambrosini <marcoambrosini@icloud.com> - - @author Marco Ambrosini <marcoambrosini@icloud.com> + - @author Maksim Sukharev <antreesy.web@gmail.com> - - - @license GNU AGPL version 3 or any later version + - @license AGPL-3.0-or-later - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as @@ -20,14 +21,7 @@ --> <template> - <div class="avatar-wrapper" - :class="{ - 'avatar-wrapper--offline': offline, - 'avatar-wrapper--small': small, - 'avatar-wrapper--condensed': condensed, - 'avatar-wrapper--highlighted': highlighted, - }" - :style="{'--condensed-overlap': condensedOverlap}"> + <div class="avatar-wrapper" :class="avatarClass" :style="{'--condensed-overlap': condensedOverlap}"> <div v-if="iconClass" class="icon" :class="[`avatar-${size}px`, iconClass]" /> @@ -36,6 +30,11 @@ :class="`avatar-${size}px`"> {{ firstLetterOfGuestName }} </div> + <div v-else-if="isBot" + class="bot" + :class="`avatar-${size}px`"> + {{ '>_' }} + </div> <NcAvatar v-else :key="id" :user="id" @@ -54,6 +53,8 @@ <script> import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js' +import { ATTENDEE } from '../../constants.js' + export default { name: 'AvatarWrapper', @@ -79,6 +80,10 @@ export default { type: Boolean, default: false, }, + medium: { + type: Boolean, + default: false, + }, condensed: { type: Boolean, default: false, @@ -122,19 +127,37 @@ export default { }, computed: { size() { - return this.small ? 22 : 44 + return this.small ? 22 : this.medium ? 32 : 44 }, // Determines which icon is displayed iconClass() { - if (!this.source || this.source === 'users' || this.isGuest || this.isDeletedUser) { + if (!this.source || this.isUser || this.isBot || this.isGuest || this.isDeletedUser) { return '' } if (this.source === 'emails') { return 'icon-mail' } + if (this.source === 'bots' && this.id === 'changelog') { + return 'icon-changelog' + } // source: groups, circles return 'icon-contacts' }, + avatarClass() { + return { + 'avatar-wrapper--offline': this.offline, + 'avatar-wrapper--small': this.small, + 'avatar-wrapper--medium': this.medium, + 'avatar-wrapper--condensed': this.condensed, + 'avatar-wrapper--highlighted': this.highlighted, + } + }, + isUser() { + return this.source === 'users' || this.source === ATTENDEE.ACTOR_TYPE.BRIDGED + }, + isBot() { + return this.source === 'bots' && this.id !== 'changelog' + }, isGuest() { return this.source === 'guests' }, @@ -161,7 +184,7 @@ export default { </script> <style lang="scss" scoped> -@import '../../assets/avatar.scss'; +@import '../../assets/avatar'; .avatar-wrapper { height: 44px; @@ -176,6 +199,13 @@ export default { @include avatar-mixin(22px); } + &--medium { + height: 32px; + width: 32px; + border-radius: 32px; + @include avatar-mixin(32px); + } + &--condensed { width: unset; height: unset; diff --git a/src/components/MessagesList/MessagesGroup/AuthorAvatar.vue b/src/components/MessagesList/MessagesGroup/AuthorAvatar.vue deleted file mode 100644 index 26645bb4f..000000000 --- a/src/components/MessagesList/MessagesGroup/AuthorAvatar.vue +++ /dev/null @@ -1,117 +0,0 @@ -<!-- - - @copyright Copyright (c) 2019 Joas Schilling <coding@schilljs.com> - - - - @author Joas Schilling <coding@schilljs.com> - - - - @license GNU AGPL version 3 or any later version - - - - This program is free software: you can redistribute it and/or modify - - it under the terms of the GNU Affero General Public License as - - published by the Free Software Foundation, either version 3 of the - - License, or (at your option) any later version. - - - - This program is distributed in the hope that it will be useful, - - but WITHOUT ANY WARRANTY; without even the implied warranty of - - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - - GNU Affero General Public License for more details. - - - - You should have received a copy of the GNU Affero General Public License - - along with this program. If not, see <http://www.gnu.org/licenses/>. ---> - -<template> - <NcAvatar v-if="isUser" - :disable-tooltip="true" - class="messages__avatar__icon" - :user="authorId" - :show-user-status="false" - :disable-menu="disableMenu" - :menu-container="menuContainer" - menu-position="left" - :display-name="displayName" /> - <div v-else-if="isDeletedUser" - class="avatar-32px guest"> - X - </div> - <div v-else-if="isGuest" - class="avatar-32px guest"> - {{ firstLetterOfGuestName }} - </div> - <div v-else-if="isChangelog" - class="avatar-32px icon icon-changelog" /> - <div v-else - class="avatar-32px bot"> - >_ - </div> -</template> - -<script> -import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js' - -import { ATTENDEE } from '../../../constants.js' - -export default { - name: 'AuthorAvatar', - components: { - NcAvatar, - }, - props: { - authorType: { - type: String, - required: true, - }, - authorId: { - type: String, - required: true, - }, - displayName: { - type: String, - required: true, - }, - }, - - computed: { - isChangelog() { - return this.authorType === 'bots' && this.authorId === 'changelog' - }, - isUser() { - return this.authorType === 'users' || this.authorType === ATTENDEE.ACTOR_TYPE.BRIDGED - }, - isDeletedUser() { - return this.authorType === 'deleted_users' - }, - isGuest() { - return this.authorType === 'guests' - }, - - firstLetterOfGuestName() { - const customName = this.displayName !== t('spreed', 'Guest') ? this.displayName : '?' - return customName.charAt(0) - }, - - menuContainer() { - return this.$store.getters.getMainContainerSelector() - }, - - disableMenu() { - // NcAvatarMenu doesn't work on Desktop - // See: https://github.com/nextcloud/talk-desktop/issues/34 - if (IS_DESKTOP) { - return true - } - // disable the menu if accessing the conversation as guest - // or the message sender is a bridged user - return this.$store.getters.getActorType() === 'guests' || this.authorType === ATTENDEE.ACTOR_TYPE.BRIDGED - }, - }, -} -</script> - -<style lang="scss" scoped> -@import '../../../assets/avatar'; - -// size of avatars of chat message authors -$author-avatar-size: 32px; -@include avatar-mixin($author-avatar-size); - -</style> diff --git a/src/components/MessagesList/MessagesGroup/MessagesGroup.spec.js b/src/components/MessagesList/MessagesGroup/MessagesGroup.spec.js index bc00b2f4c..893bbf9e5 100644 --- a/src/components/MessagesList/MessagesGroup/MessagesGroup.spec.js +++ b/src/components/MessagesList/MessagesGroup/MessagesGroup.spec.js @@ -82,10 +82,10 @@ describe('MessagesGroup.vue', () => { }, }) - const avatarEl = wrapper.findComponent({ name: 'AuthorAvatar' }) - expect(avatarEl.attributes('authortype')).toBe(ATTENDEE.ACTOR_TYPE.USERS) - expect(avatarEl.attributes('authorid')).toBe('actor-1') - expect(avatarEl.attributes('displayname')).toBe('actor one') + const avatarEl = wrapper.findComponent({ name: 'AvatarWrapper' }) + expect(avatarEl.attributes('source')).toBe(ATTENDEE.ACTOR_TYPE.USERS) + expect(avatarEl.attributes('id')).toBe('actor-1') + expect(avatarEl.attributes('name')).toBe('actor one') const authorEl = wrapper.find('.messages__author') expect(authorEl.text()).toBe('actor one') @@ -155,7 +155,7 @@ describe('MessagesGroup.vue', () => { }, }) - const avatarEl = wrapper.findComponent({ name: 'AuthorAvatar' }) + const avatarEl = wrapper.findComponent({ name: 'AvatarWrapper' }) expect(avatarEl.exists()).toBe(false) const messagesEl = wrapper.findAllComponents({ name: 'Message' }) @@ -225,10 +225,10 @@ describe('MessagesGroup.vue', () => { }, }) - const avatarEl = wrapper.findComponent({ name: 'AuthorAvatar' }) - expect(avatarEl.attributes('authortype')).toBe(ATTENDEE.ACTOR_TYPE.GUESTS) - expect(avatarEl.attributes('authorid')).toBe('actor-1') - expect(avatarEl.attributes('displayname')).toBe('guest-one-display-name') + const avatarEl = wrapper.findComponent({ name: 'AvatarWrapper' }) + expect(avatarEl.attributes('source')).toBe(ATTENDEE.ACTOR_TYPE.GUESTS) + expect(avatarEl.attributes('id')).toBe('actor-1') + expect(avatarEl.attributes('name')).toBe('guest-one-display-name') const authorEl = wrapper.find('.messages__author') expect(authorEl.text()).toBe('guest-one-display-name') @@ -280,10 +280,10 @@ describe('MessagesGroup.vue', () => { }, }) - const avatarEl = wrapper.findComponent({ name: 'AuthorAvatar' }) - expect(avatarEl.attributes('authortype')).toBe(ATTENDEE.ACTOR_TYPE.USERS) - expect(avatarEl.attributes('authorid')).toBe('actor-1') - expect(avatarEl.attributes('displayname')).toBe('Deleted user') + const avatarEl = wrapper.findComponent({ name: 'AvatarWrapper' }) + expect(avatarEl.attributes('source')).toBe(ATTENDEE.ACTOR_TYPE.USERS) + expect(avatarEl.attributes('id')).toBe('actor-1') + expect(avatarEl.attributes('name')).toBe('Deleted user') const authorEl = wrapper.find('.messages__author') expect(authorEl.text()).toBe('Deleted user') diff --git a/src/components/MessagesList/MessagesGroup/MessagesGroup.vue b/src/components/MessagesList/MessagesGroup/MessagesGroup.vue index 0a1a71ba8..476ff0a25 100644 --- a/src/components/MessagesList/MessagesGroup/MessagesGroup.vue +++ b/src/components/MessagesList/MessagesGroup/MessagesGroup.vue @@ -3,7 +3,7 @@ - - @author Marco Ambrosini <marcoambrosini@icloud.com> - - - @license GNU AGPL version 3 or any later version + - @license AGPL-3.0-or-later - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as @@ -22,9 +22,12 @@ <template> <div class="wrapper"> <div class="messages__avatar"> - <AuthorAvatar :author-type="actorType" - :author-id="actorId" - :display-name="actorDisplayName" /> + <AvatarWrapper :id="actorId" + :name="actorDisplayName" + :source="actorType" + :disable-menu="disableMenu" + disable-tooltip + medium /> </div> <ul class="messages"> <li class="messages__author" aria-level="4"> @@ -44,7 +47,7 @@ </template> <script> -import AuthorAvatar from './AuthorAvatar.vue' +import AvatarWrapper from '../../AvatarWrapper/AvatarWrapper.vue' import Message from './Message/Message.vue' import { ATTENDEE } from '../../../constants.js' @@ -54,7 +57,7 @@ export default { name: 'MessagesGroup', components: { - AuthorAvatar, + AvatarWrapper, Message, }, inheritAttrs: false, @@ -128,6 +131,12 @@ export default { return displayName }, + + disableMenu() { + // disable the menu if accessing the conversation as guest + // or the message sender is a bridged user + return this.$store.getters.getActorType() === 'guests' || this.actorType === ATTENDEE.ACTOR_TYPE.BRIDGED + }, }, methods: { @@ -151,6 +160,7 @@ export default { display: flex; margin: auto; padding: 0; + &:focus { background-color: rgba(47, 47, 47, 0.068); } @@ -163,6 +173,7 @@ export default { flex-direction: column; width: 100%; min-width: 0; + &__avatar { position: sticky; top: 0; |