diff options
author | Maksim Sukharev <antreesy.web@gmail.com> | 2023-10-02 17:20:04 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-02 17:20:04 +0200 |
commit | cc903fc46f63686ae8793c6fbb5c1c3fc4db6f48 (patch) | |
tree | cb8c31cd5f7a300a1760fcbacc74b8902245be87 | |
parent | 5f3485853032919be5ae0888cb7bd3fbbb3fc9a9 (diff) | |
parent | e4692febc97dc52d40369de67750e9a3d43b114b (diff) |
Merge pull request #10610 from nextcloud/fix/10282/increase-avatars-in-call
fix(NcAvatar) increase avatar sizes in call
31 files changed, 226 insertions, 355 deletions
diff --git a/src/assets/avatar.scss b/src/assets/avatar.scss deleted file mode 100644 index 54645ee12..000000000 --- a/src/assets/avatar.scss +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @copyright Copyright (c) 2020 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/>. - * - */ -@use 'sass:math'; - -@import 'variables'; - - -@mixin avatar-mixin($size: 32px) { - .avatar-#{$size} { - position: sticky; - top: 0; - width: $size; - height: $size; - line-height: $size; - font-size: math.div($size, 2); - border-radius: 50%; - - &.icon { - border-radius: 50%; - height: $size; - width: $size; - background-color: var(--color-background-darker); - } - - &.bot { - padding-left: 5px; - line-height: $size; - border-radius: 50%; - background-color: var(--color-background-darker); - } - - &.guest { - line-height: $size; - font-size: math.div($size, 2); - color: $color-guests-avatar; - background-color: $color-background-guests-avatar; - padding: 0; - display: block; - text-align: center; - margin-left: auto; - margin-right: auto; - } - } -} diff --git a/src/assets/variables.scss b/src/assets/variables.scss index 8aeb4f402..ea8f10de2 100644 --- a/src/assets/variables.scss +++ b/src/assets/variables.scss @@ -20,66 +20,14 @@ * */ -@use 'sass:math'; - -// https://uxplanet.org/7-rules-for-mobile-ui-button-design-e9cf2ea54556 -// recommended is 48px -// 44px is what we choose and have very good visual-to-usability ratio -$clickable-area: 44px; - -// background icon size -// also used for the scss icon font -$icon-size: 16px; - -// icon padding for a $clickable-area width and a $icon-size icon -// ( 44px - 16px ) / 2 -$icon-margin: math.div($clickable-area - $icon-size, 2); - -// transparency background for icons -$icon-focus-bg: rgba(127, 127, 127, .25); - -// popovermenu arrow width from the triangle center -$arrow-width: 9px; - -// opacities -$opacity_disabled: .5; -$opacity_normal: .7; -$opacity_full: 1; - -// menu round background hover feedback -// good looking on dark AND white bg -$action-background-hover: rgba(127, 127, 127, .25); - -// various structure data used in the -// `NcAppNavigation` component -$header-height: 50px; -$navigation-width: 300px; - -// mobile breakpoint -$breakpoint-mobile: 1024px; - //messages list max width $messages-list-max-width: 800px; -//message max width -$message-max-width: 680px; - //message utils width $message-utils-width: 100px; -//message form max height -$message-form-max-height: 180px; - +// background color of call container $color-call-background: rgba(34, 34, 34, 0.8); -$color-guests-avatar: #ffffff; -$color-background-guests-avatar: #b9b9b9; - - -//chat font size -$chat-font-size: 15px; - -//chat line height -$chat-line-height: 1.6em; // transition $transition-duration-quick: var(--animation-quick, 100ms); diff --git a/src/components/AvatarWrapper/AvatarWrapper.spec.js b/src/components/AvatarWrapper/AvatarWrapper.spec.js index c7f0eaf9b..1c3216033 100644 --- a/src/components/AvatarWrapper/AvatarWrapper.spec.js +++ b/src/components/AvatarWrapper/AvatarWrapper.spec.js @@ -49,17 +49,18 @@ describe('AvatarWrapper.vue', () => { expect(avatar.exists()).toBeFalsy() }) - test('component renders NcAvatar with smaller size', () => { + test('component renders NcAvatar with specified size', () => { + const size = 22 const wrapper = shallowMount(AvatarWrapper, { store, propsData: { name: USER_NAME, - small: true, + size, }, }) const avatar = wrapper.findComponent(NcAvatar) - expect(avatar.props('size')).toBe(22) + expect(avatar.props('size')).toBe(size) }) test('component pass props to NcAvatar correctly', async () => { diff --git a/src/components/AvatarWrapper/AvatarWrapper.vue b/src/components/AvatarWrapper/AvatarWrapper.vue index 196be555b..88524a996 100644 --- a/src/components/AvatarWrapper/AvatarWrapper.vue +++ b/src/components/AvatarWrapper/AvatarWrapper.vue @@ -21,18 +21,12 @@ --> <template> - <div class="avatar-wrapper" :class="avatarClass" :style="{'--condensed-overlap': condensedOverlap}"> - <div v-if="iconClass" - class="icon" - :class="[`avatar-${size}px`, iconClass]" /> - <div v-else-if="isGuest || isDeletedUser" - class="guest" - :class="`avatar-${size}px`"> + <div class="avatar-wrapper" :class="avatarClass" :style="avatarStyle"> + <div v-if="iconClass" class="avatar icon" :class="[iconClass]" /> + <div v-else-if="isGuest || isDeletedUser" class="avatar guest"> {{ firstLetterOfGuestName }} </div> - <div v-else-if="isBot" - class="bot" - :class="`avatar-${size}px`"> + <div v-else-if="isBot" class="avatar bot"> {{ '>_' }} </div> <NcAvatar v-else @@ -53,7 +47,7 @@ <script> import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js' -import { ATTENDEE } from '../../constants.js' +import { ATTENDEE, AVATAR } from '../../constants.js' export default { @@ -76,13 +70,9 @@ export default { type: String, default: null, }, - small: { - type: Boolean, - default: false, - }, - medium: { - type: Boolean, - default: false, + size: { + type: Number, + default: AVATAR.SIZE.DEFAULT, }, condensed: { type: Boolean, @@ -126,9 +116,6 @@ export default { }, }, computed: { - size() { - return this.small ? 22 : this.medium ? 32 : 44 - }, // Determines which icon is displayed iconClass() { if (!this.source || this.isUser || this.isBot || this.isGuest || this.isDeletedUser) { @@ -146,12 +133,16 @@ export default { 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, } }, + avatarStyle() { + return { + '--avatar-size': this.size + 'px', + '--condensed-overlap': this.condensedOverlap, + } + }, isUser() { return this.source === 'users' || this.source === ATTENDEE.ACTOR_TYPE.BRIDGED }, @@ -184,26 +175,38 @@ export default { </script> <style lang="scss" scoped> -@import '../../assets/avatar'; - .avatar-wrapper { - height: 44px; - width: 44px; - border-radius: 44px; - @include avatar-mixin(44px); - - &--small { - height: 22px; - width: 22px; - border-radius: 22px; - @include avatar-mixin(22px); - } + height: var(--avatar-size); + width: var(--avatar-size); + border-radius: var(--avatar-size); + + .avatar { + position: sticky; + top: 0; + width: var(--avatar-size); + height: var(--avatar-size); + line-height: var(--avatar-size); + font-size: calc(var(--avatar-size) / 2); + border-radius: 50%; + + &.icon { + background-color: var(--color-background-darker); + } + + &.bot { + padding-left: 5px; + background-color: var(--color-background-darker); + } - &--medium { - height: 32px; - width: 32px; - border-radius: 32px; - @include avatar-mixin(32px); + &.guest { + color: #ffffff; + background-color: #b9b9b9; + padding: 0; + display: block; + text-align: center; + margin-left: auto; + margin-right: auto; + } } &--condensed { diff --git a/src/components/CallView/Grid/Grid.vue b/src/components/CallView/Grid/Grid.vue index c3ca10f6a..c3f4e2ace 100644 --- a/src/components/CallView/Grid/Grid.vue +++ b/src/components/CallView/Grid/Grid.vue @@ -858,8 +858,6 @@ export default { </script> <style lang="scss" scoped> -@import '../../../assets/variables'; - .grid-main-wrapper { position: relative; width: 100%; diff --git a/src/components/CallView/shared/LocalVideo.vue b/src/components/CallView/shared/LocalVideo.vue index f88b4e8af..247da1639 100644 --- a/src/components/CallView/shared/LocalVideo.vue +++ b/src/components/CallView/shared/LocalVideo.vue @@ -3,7 +3,7 @@ - - @author Grigorii Shartsev <me@shgk.me> - - - @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 @@ -42,19 +42,13 @@ <VideoBackground v-if="isGrid || isStripe" :display-name="displayName" :user="userId" /> - <NcAvatar v-if="userId" + <AvatarWrapper :id="userId" + :name="displayName" + :source="actorType" :size="avatarSize" - :disable-menu="true" - :disable-tooltip="true" - :show-user-status="false" - :user="userId" - :display-name="displayName" + disable-menu + disable-tooltip :class="avatarClass" /> - <div v-if="!userId" - :class="guestAvatarClass" - class="avatar guest"> - {{ firstLetterOfGuestName }} - </div> </div> <div v-if="mouseover && isSelectable" class="hover-shadow" /> @@ -76,11 +70,12 @@ import SHA1 from 'crypto-js/sha1.js' import { showError, showInfo, TOAST_PERMANENT_TIMEOUT } from '@nextcloud/dialogs' -import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js' import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' +import AvatarWrapper from '../../AvatarWrapper/AvatarWrapper.vue' import VideoBackground from './VideoBackground.vue' +import { AVATAR } from '../../../constants.js' import video from '../../../mixins/video.js' import { useGuestNameStore } from '../../../stores/guestName.js' import { ConnectionState } from '../../../utils/webrtc/models/CallParticipantModel.js' @@ -90,7 +85,7 @@ export default { name: 'LocalVideo', components: { - NcAvatar, + AvatarWrapper, NcButton, VideoBackground, }, @@ -110,7 +105,7 @@ export default { type: Object, required: true, }, - useConstrainedLayout: { + isGrid: { type: Boolean, default: false, }, @@ -175,7 +170,7 @@ export default { }, videoWrapperStyle() { - if (!this.containerAspectRatio || !this.videoAspectRatio || !this.isBig) { + if (!this.containerAspectRatio || !this.videoAspectRatio || !this.isBig || this.isGrid) { return } return (this.containerAspectRatio > this.videoAspectRatio) @@ -187,13 +182,12 @@ export default { return this.$store.getters.getUserId() }, - displayName() { - return this.$store.getters.getDisplayName() + actorType() { + return this.$store.getters.getActorType() }, - firstLetterOfGuestName() { - const customName = this.guestName !== t('spreed', 'Guest') ? this.guestName : '?' - return customName.charAt(0) + displayName() { + return this.$store.getters.getDisplayName() }, sessionHash() { @@ -214,7 +208,13 @@ export default { }, avatarSize() { - return this.useConstrainedLayout ? 64 : 128 + if (this.isStripe || (!this.isBig && !this.isGrid)) { + return AVATAR.SIZE.LARGE + } else if (!this.containerAspectRatio) { + return AVATAR.SIZE.FULL + } else { + return Math.min(AVATAR.SIZE.FULL, this.$refs.videoContainer.clientHeight / 2, this.$refs.videoContainer.clientWidth / 2) + } }, avatarClass() { @@ -223,12 +223,6 @@ export default { } }, - guestAvatarClass() { - return Object.assign(this.avatarClass, { - ['avatar-' + this.avatarSize + 'px']: true, - }) - }, - localStreamVideoError() { return this.localMediaModel.attributes.localStream && this.localMediaModel.attributes.localStreamRequestVideoError }, @@ -294,7 +288,7 @@ export default { // Set initial state this._setLocalStream(this.localMediaModel.attributes.localStream) - if (this.isBig) { + if (this.isBig || this.isGrid) { this.resizeObserver = new ResizeObserver(this.updateContainerAspectRatio) this.resizeObserver.observe(this.$refs.videoContainer) } @@ -364,11 +358,6 @@ export default { </script> <style lang="scss" scoped> -@import '../../../assets/variables'; -@import '../../../assets/avatar'; -@include avatar-mixin(64px); -@include avatar-mixin(128px); - .not-connected { video, .avatar-container { @@ -379,12 +368,12 @@ export default { // Always display the local video in the last row .localVideoContainer { grid-row-end: -1; - border-radius: calc(var(--default-clickable-area)/2); + border-radius: calc(var(--default-clickable-area) / 2); z-index: 1; } .video-container-grid { - position:relative; + position: relative; height: 100%; width: 100%; overflow: hidden; @@ -455,7 +444,7 @@ export default { left: 0; box-shadow: inset 0 0 0 3px white; cursor: pointer; - border-radius: calc(var(--default-clickable-area)/2); + border-radius: calc(var(--default-clickable-area) / 2); } .bottom-bar { @@ -467,13 +456,16 @@ export default { justify-content: center; align-items: center; height: 40px; + &--big { justify-content: center; height: 48px;< |