diff --git a/src/platform/web/ui/AvatarView.js b/src/platform/web/ui/AvatarView.js new file mode 100644 index 00000000..22381838 --- /dev/null +++ b/src/platform/web/ui/AvatarView.js @@ -0,0 +1,84 @@ +import {BaseUpdateView} from "./general/BaseUpdateView.js"; +import {renderStaticAvatar, renderImg} from "./avatar.js"; +import {text} from "./general/html.js"; + +/* +optimization to not use a sub view when changing between img and text +because there can be many many instances of this view +*/ + +export class AvatarView extends BaseUpdateView { + /** + * @param {ViewModel} value view model with {avatarUrl, avatarColorNumber, avatarTitle, avatarLetter} + * @param {Number} size + */ + constructor(value, size) { + super(value); + this._root = null; + this._avatarUrl = null; + this._avatarTitle = null; + this._avatarLetter = null; + this._size = size; + } + + _avatarUrlChanged() { + if (this.value.avatarUrl(this._size) !== this._avatarUrl) { + this._avatarUrl = this.value.avatarUrl(this._size); + return true; + } + return false; + } + + _avatarTitleChanged() { + if (this.value.avatarTitle !== this._avatarTitle) { + this._avatarTitle = this.value.avatarTitle; + return true; + } + return false; + } + + _avatarLetterChanged() { + if (this.value.avatarLetter !== this._avatarLetter) { + this._avatarLetter = this.value.avatarLetter; + return true; + } + return false; + } + + mount(options) { + this._avatarUrlChanged(); + this._avatarLetterChanged(); + this._avatarTitleChanged(); + this._root = renderStaticAvatar(this.value, this._size); + // takes care of update being called when needed + super.mount(options); + return this._root; + } + + root() { + return this._root; + } + + update(vm) { + // important to always call _...changed for every prop + if (this._avatarUrlChanged()) { + // avatarColorNumber won't change, it's based on room/user id + const bgColorClass = `usercolor${vm.avatarColorNumber}`; + if (vm.avatarUrl(this._size)) { + this._root.replaceChild(renderImg(vm, this._size), this._root.firstChild); + this._root.classList.remove(bgColorClass); + } else { + this._root.replaceChild(text(vm.avatarLetter), this._root.firstChild); + this._root.classList.add(bgColorClass); + } + } + const hasAvatar = !!vm.avatarUrl(this._size); + if (this._avatarTitleChanged() && hasAvatar) { + const img = this._root.firstChild; + img.setAttribute("title", vm.avatarTitle); + } + if (this._avatarLetterChanged() && !hasAvatar) { + this._root.firstChild.textContent = vm.avatarLetter; + } + } +} diff --git a/src/platform/web/ui/avatar.js b/src/platform/web/ui/avatar.js index 093cfd69..bda44db0 100644 --- a/src/platform/web/ui/avatar.js +++ b/src/platform/web/ui/avatar.js @@ -15,89 +15,6 @@ limitations under the License. */ import {tag, text, classNames} from "./general/html.js"; -import {BaseUpdateView} from "./general/BaseUpdateView.js"; - -/* -optimization to not use a sub view when changing between img and text -because there can be many many instances of this view -*/ - -export class AvatarView extends BaseUpdateView { - /** - * @param {ViewModel} value view model with {avatarUrl, avatarColorNumber, avatarTitle, avatarLetter} - * @param {Number} size - */ - constructor(value, size) { - super(value); - this._root = null; - this._avatarUrl = null; - this._avatarTitle = null; - this._avatarLetter = null; - this._size = size; - } - - _avatarUrlChanged() { - if (this.value.avatarUrl(this._size) !== this._avatarUrl) { - this._avatarUrl = this.value.avatarUrl(this._size); - return true; - } - return false; - } - - _avatarTitleChanged() { - if (this.value.avatarTitle !== this._avatarTitle) { - this._avatarTitle = this.value.avatarTitle; - return true; - } - return false; - } - - _avatarLetterChanged() { - if (this.value.avatarLetter !== this._avatarLetter) { - this._avatarLetter = this.value.avatarLetter; - return true; - } - return false; - } - - mount(options) { - this._avatarUrlChanged(); - this._avatarLetterChanged(); - this._avatarTitleChanged(); - this._root = renderStaticAvatar(this.value, this._size); - // takes care of update being called when needed - super.mount(options); - return this._root; - } - - root() { - return this._root; - } - - update(vm) { - // important to always call _...changed for every prop - if (this._avatarUrlChanged()) { - // avatarColorNumber won't change, it's based on room/user id - const bgColorClass = `usercolor${vm.avatarColorNumber}`; - if (vm.avatarUrl(this._size)) { - this._root.replaceChild(renderImg(vm, this._size), this._root.firstChild); - this._root.classList.remove(bgColorClass); - } else { - this._root.replaceChild(text(vm.avatarLetter), this._root.firstChild); - this._root.classList.add(bgColorClass); - } - } - const hasAvatar = !!vm.avatarUrl(this._size); - if (this._avatarTitleChanged() && hasAvatar) { - const img = this._root.firstChild; - img.setAttribute("title", vm.avatarTitle); - } - if (this._avatarLetterChanged() && !hasAvatar) { - this._root.firstChild.textContent = vm.avatarLetter; - } - } -} - /** * @param {Object} vm view model with {avatarUrl, avatarColorNumber, avatarTitle, avatarLetter} * @param {Number} size @@ -118,7 +35,7 @@ export function renderStaticAvatar(vm, size, extraClasses = undefined) { return tag.div({className: avatarClasses, 'data-avatar-letter': vm.avatarLetter}, [avatarContent]); } -function renderImg(vm, size) { +export function renderImg(vm, size) { const sizeStr = size.toString(); return tag.img({src: vm.avatarUrl(size), width: sizeStr, height: sizeStr, title: vm.avatarTitle}); } diff --git a/src/platform/web/ui/session/leftpanel/RoomTileView.js b/src/platform/web/ui/session/leftpanel/RoomTileView.js index 84b38b62..228addba 100644 --- a/src/platform/web/ui/session/leftpanel/RoomTileView.js +++ b/src/platform/web/ui/session/leftpanel/RoomTileView.js @@ -16,7 +16,7 @@ limitations under the License. */ import {TemplateView} from "../../general/TemplateView.js"; -import {AvatarView} from "../../avatar.js"; +import {AvatarView} from "../../AvatarView.js"; export class RoomTileView extends TemplateView { render(t, vm) { diff --git a/src/platform/web/ui/session/rightpanel/RoomDetailsView.js b/src/platform/web/ui/session/rightpanel/RoomDetailsView.js index a6d1a81f..8357b722 100644 --- a/src/platform/web/ui/session/rightpanel/RoomDetailsView.js +++ b/src/platform/web/ui/session/rightpanel/RoomDetailsView.js @@ -1,6 +1,6 @@ import {TemplateView} from "../../general/TemplateView.js"; import {classNames, tag} from "../../general/html.js"; -import {AvatarView} from "../../avatar.js"; +import {AvatarView} from "../../AvatarView.js"; export class RoomDetailsView extends TemplateView { render(t, vm) { diff --git a/src/platform/web/ui/session/room/RoomView.js b/src/platform/web/ui/session/room/RoomView.js index f8e84f87..ccad448f 100644 --- a/src/platform/web/ui/session/room/RoomView.js +++ b/src/platform/web/ui/session/room/RoomView.js @@ -22,7 +22,7 @@ import {TimelineList} from "./TimelineList.js"; import {TimelineLoadingView} from "./TimelineLoadingView.js"; import {MessageComposer} from "./MessageComposer.js"; import {RoomArchivedView} from "./RoomArchivedView.js"; -import {AvatarView} from "../../avatar.js"; +import {AvatarView} from "../../AvatarView.js"; export class RoomView extends TemplateView { constructor(options) {