Merge pull request #331 from vector-im/bwindels/dedupe-avatar-sizes
Don't repeat avatar sizes in view models
This commit is contained in:
commit
0298f31ec7
7 changed files with 36 additions and 39 deletions
|
@ -47,3 +47,11 @@ function hashCode(str) {
|
||||||
export function getIdentifierColorNumber(id) {
|
export function getIdentifierColorNumber(id) {
|
||||||
return (hashCode(id) % 8) + 1;
|
return (hashCode(id) % 8) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getAvatarHttpUrl(avatarUrl, cssSize, platform, mediaRepository) {
|
||||||
|
if (avatarUrl) {
|
||||||
|
const imageSize = cssSize * platform.devicePixelRatio;
|
||||||
|
return mediaRepository.mxcUrlThumbnail(avatarUrl, imageSize, imageSize, "crop");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {avatarInitials, getIdentifierColorNumber} from "../../avatar.js";
|
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
|
||||||
import {ViewModel} from "../../ViewModel.js";
|
import {ViewModel} from "../../ViewModel.js";
|
||||||
|
|
||||||
const KIND_ORDER = ["invite", "room"];
|
const KIND_ORDER = ["invite", "room"];
|
||||||
|
@ -75,12 +75,8 @@ export class BaseTileViewModel extends ViewModel {
|
||||||
return getIdentifierColorNumber(this._avatarSource.id);
|
return getIdentifierColorNumber(this._avatarSource.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
get avatarUrl() {
|
avatarUrl(size) {
|
||||||
if (this._avatarSource.avatarUrl) {
|
return getAvatarHttpUrl(this._avatarSource.avatarUrl, size, this.platform, this._avatarSource.mediaRepository);
|
||||||
const size = 32 * this.platform.devicePixelRatio;
|
|
||||||
return this._avatarSource.mediaRepository.mxcUrlThumbnail(this._avatarSource.avatarUrl, size, size, "crop");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get avatarTitle() {
|
get avatarTitle() {
|
||||||
|
|
|
@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {avatarInitials, getIdentifierColorNumber} from "../../avatar.js";
|
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
|
||||||
import {ViewModel} from "../../ViewModel.js";
|
import {ViewModel} from "../../ViewModel.js";
|
||||||
|
|
||||||
export class InviteViewModel extends ViewModel {
|
export class InviteViewModel extends ViewModel {
|
||||||
|
@ -60,12 +60,8 @@ export class InviteViewModel extends ViewModel {
|
||||||
return getIdentifierColorNumber(this._invite.id)
|
return getIdentifierColorNumber(this._invite.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
get avatarUrl() {
|
avatarUrl(size) {
|
||||||
if (this._invite.avatarUrl) {
|
return getAvatarHttpUrl(this._invite.avatarUrl, size, this.platform, this._mediaRepository);
|
||||||
const size = 128 * this.platform.devicePixelRatio;
|
|
||||||
return this._mediaRepository.mxcUrlThumbnail(this._invite.avatarUrl, size, size, "crop");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_createRoomDescription() {
|
_createRoomDescription() {
|
||||||
|
@ -153,12 +149,8 @@ class RoomMemberViewModel {
|
||||||
return getIdentifierColorNumber(this._member.userId);
|
return getIdentifierColorNumber(this._member.userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
get avatarUrl() {
|
avatarUrl(size) {
|
||||||
if (this._member.avatarUrl) {
|
return getAvatarHttpUrl(this._member.avatarUrl, size, this._platform, this._mediaRepository);
|
||||||
const size = 24 * this._platform.devicePixelRatio;
|
|
||||||
return this._mediaRepository.mxcUrlThumbnail(this._member.avatarUrl, size, size, "crop");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get avatarTitle() {
|
get avatarTitle() {
|
||||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {TimelineViewModel} from "./timeline/TimelineViewModel.js";
|
import {TimelineViewModel} from "./timeline/TimelineViewModel.js";
|
||||||
import {avatarInitials, getIdentifierColorNumber} from "../../avatar.js";
|
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar.js";
|
||||||
import {ViewModel} from "../../ViewModel.js";
|
import {ViewModel} from "../../ViewModel.js";
|
||||||
|
|
||||||
export class RoomViewModel extends ViewModel {
|
export class RoomViewModel extends ViewModel {
|
||||||
|
@ -120,12 +120,8 @@ export class RoomViewModel extends ViewModel {
|
||||||
return getIdentifierColorNumber(this._room.id)
|
return getIdentifierColorNumber(this._room.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
get avatarUrl() {
|
avatarUrl(size) {
|
||||||
if (this._room.avatarUrl) {
|
return getAvatarHttpUrl(this._room.avatarUrl, size, this.platform, this._room.mediaRepository);
|
||||||
const size = 32 * this.platform.devicePixelRatio;
|
|
||||||
return this._room.mediaRepository.mxcUrlThumbnail(this._room.avatarUrl, size, size, "crop");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get avatarTitle() {
|
get avatarTitle() {
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {SimpleTile} from "./SimpleTile.js";
|
import {SimpleTile} from "./SimpleTile.js";
|
||||||
import {getIdentifierColorNumber, avatarInitials} from "../../../../avatar.js";
|
import {getIdentifierColorNumber, avatarInitials, getAvatarHttpUrl} from "../../../../avatar.js";
|
||||||
|
|
||||||
export class MessageTile extends SimpleTile {
|
export class MessageTile extends SimpleTile {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
|
@ -50,11 +50,8 @@ export class MessageTile extends SimpleTile {
|
||||||
return getIdentifierColorNumber(this._entry.sender);
|
return getIdentifierColorNumber(this._entry.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
get avatarUrl() {
|
avatarUrl(size) {
|
||||||
if (this._entry.avatarUrl) {
|
return getAvatarHttpUrl(this._entry.avatarUrl, size, this.platform, this._mediaRepository);
|
||||||
return this._mediaRepository.mxcUrlThumbnail(this._entry.avatarUrl, 30, 30, "crop");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get avatarLetter() {
|
get avatarLetter() {
|
||||||
|
|
|
@ -37,8 +37,8 @@ export class AvatarView extends BaseUpdateView {
|
||||||
}
|
}
|
||||||
|
|
||||||
_avatarUrlChanged() {
|
_avatarUrlChanged() {
|
||||||
if (this.value.avatarUrl !== this._avatarUrl) {
|
if (this.value.avatarUrl(this._size) !== this._avatarUrl) {
|
||||||
this._avatarUrl = this.value.avatarUrl;
|
this._avatarUrl = this.value.avatarUrl(this._size);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -79,7 +79,7 @@ export class AvatarView extends BaseUpdateView {
|
||||||
if (this._avatarUrlChanged()) {
|
if (this._avatarUrlChanged()) {
|
||||||
// avatarColorNumber won't change, it's based on room/user id
|
// avatarColorNumber won't change, it's based on room/user id
|
||||||
const bgColorClass = `usercolor${vm.avatarColorNumber}`;
|
const bgColorClass = `usercolor${vm.avatarColorNumber}`;
|
||||||
if (vm.avatarUrl) {
|
if (vm.avatarUrl(this._size)) {
|
||||||
this._root.replaceChild(renderImg(vm, this._size), this._root.firstChild);
|
this._root.replaceChild(renderImg(vm, this._size), this._root.firstChild);
|
||||||
this._root.classList.remove(bgColorClass);
|
this._root.classList.remove(bgColorClass);
|
||||||
} else {
|
} else {
|
||||||
|
@ -87,7 +87,7 @@ export class AvatarView extends BaseUpdateView {
|
||||||
this._root.classList.add(bgColorClass);
|
this._root.classList.add(bgColorClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const hasAvatar = !!vm.avatarUrl;
|
const hasAvatar = !!vm.avatarUrl(this._size);
|
||||||
if (this._avatarTitleChanged() && hasAvatar) {
|
if (this._avatarTitleChanged() && hasAvatar) {
|
||||||
const img = this._root.firstChild;
|
const img = this._root.firstChild;
|
||||||
img.setAttribute("title", vm.avatarTitle);
|
img.setAttribute("title", vm.avatarTitle);
|
||||||
|
@ -104,7 +104,7 @@ export class AvatarView extends BaseUpdateView {
|
||||||
* @return {Element}
|
* @return {Element}
|
||||||
*/
|
*/
|
||||||
export function renderStaticAvatar(vm, size, extraClasses = undefined) {
|
export function renderStaticAvatar(vm, size, extraClasses = undefined) {
|
||||||
const hasAvatar = !!vm.avatarUrl;
|
const hasAvatar = !!vm.avatarUrl(size);
|
||||||
let avatarClasses = classNames({
|
let avatarClasses = classNames({
|
||||||
avatar: true,
|
avatar: true,
|
||||||
[`size-${size}`]: true,
|
[`size-${size}`]: true,
|
||||||
|
@ -119,5 +119,5 @@ export function renderStaticAvatar(vm, size, extraClasses = undefined) {
|
||||||
|
|
||||||
function renderImg(vm, size) {
|
function renderImg(vm, size) {
|
||||||
const sizeStr = size.toString();
|
const sizeStr = size.toString();
|
||||||
return tag.img({src: vm.avatarUrl, width: sizeStr, height: sizeStr, title: vm.avatarTitle});
|
return tag.img({src: vm.avatarUrl(size), width: sizeStr, height: sizeStr, title: vm.avatarTitle});
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,14 @@ limitations under the License.
|
||||||
font-size: calc(var(--avatar-size) * 0.6);
|
font-size: calc(var(--avatar-size) * 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hydrogen .avatar.size-30 {
|
||||||
|
--avatar-size: 30px;
|
||||||
|
width: var(--avatar-size);
|
||||||
|
height: var(--avatar-size);
|
||||||
|
line-height: var(--avatar-size);
|
||||||
|
font-size: calc(var(--avatar-size) * 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
.hydrogen .avatar.size-24 {
|
.hydrogen .avatar.size-24 {
|
||||||
--avatar-size: 24px;
|
--avatar-size: 24px;
|
||||||
width: var(--avatar-size);
|
width: var(--avatar-size);
|
||||||
|
|
Reference in a new issue