Browse Source

Avatar stripped thumbnails

Render avatar thumb if have queue
master
morethanwords 3 years ago
parent
commit
bdc4851210
  1. 29
      src/components/avatar.ts
  2. 7
      src/helpers/dom/renderImageFromUrl.ts
  3. 60
      src/lib/appManagers/appProfileManager.ts
  4. 10
      src/scss/partials/_avatar.scss

29
src/components/avatar.ts

@ -179,6 +179,22 @@ export default class AvatarElement extends HTMLElement { @@ -179,6 +179,22 @@ export default class AvatarElement extends HTMLElement {
}
}
private r(onlyThumb = false) {
const res = appProfileManager.putPhoto(this, this.peerId, this.isDialog, this.peerTitle, onlyThumb);
const promise = res ? res.loadPromise : Promise.resolve();
if(this.loadPromises) {
if(res && res.cached) {
this.loadPromises.push(promise);
}
promise.finally(() => {
this.loadPromises = undefined;
});
}
return res;
}
public update() {
if(this.lazyLoadQueue) {
if(!seen.has(this.peerId)) {
@ -193,6 +209,8 @@ export default class AvatarElement extends HTMLElement { @@ -193,6 +209,8 @@ export default class AvatarElement extends HTMLElement {
set.add(this);
this.r(true);
this.lazyLoadQueue.push({
div: this,
load: () => {
@ -209,17 +227,8 @@ export default class AvatarElement extends HTMLElement { @@ -209,17 +227,8 @@ export default class AvatarElement extends HTMLElement {
seen.add(this.peerId);
const res = appProfileManager.putPhoto(this, this.peerId, this.isDialog, this.peerTitle);
const res = this.r();
const promise = res ? res.loadPromise : Promise.resolve();
if(this.loadPromises) {
if(res && res.cached) {
this.loadPromises.push(promise);
}
promise.finally(() => {
this.loadPromises = undefined;
});
}
if(this.addedToQueue) {
promise.finally(() => {

7
src/helpers/dom/renderImageFromUrl.ts

@ -12,11 +12,11 @@ const set = (elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLVideoE @@ -12,11 +12,11 @@ const set = (elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLVideoE
};
// проблема функции в том, что она не подходит для ссылок, пригодна только для blob'ов, потому что обычным ссылкам нужен 'load' каждый раз.
export default function renderImageFromUrl(elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLVideoElement, url: string, callback?: (err?: Event) => void, useCache = true): boolean {
export default async function renderImageFromUrl(elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLVideoElement, url: string, callback?: (err?: Event) => void, useCache = true) {
if(!url) {
console.error('renderImageFromUrl: no url?', elem, url);
callback && callback();
return false;
return;
}
if(((loadedURLs[url]/* && false */) && useCache) || elem instanceof HTMLVideoElement) {
@ -25,7 +25,6 @@ export default function renderImageFromUrl(elem: HTMLElement | HTMLImageElement @@ -25,7 +25,6 @@ export default function renderImageFromUrl(elem: HTMLElement | HTMLImageElement
}
callback && callback();
return true;
} else {
const isImage = elem instanceof HTMLImageElement;
const loader = isImage ? elem as HTMLImageElement : new Image();
@ -53,7 +52,5 @@ export default function renderImageFromUrl(elem: HTMLElement | HTMLImageElement @@ -53,7 +52,5 @@ export default function renderImageFromUrl(elem: HTMLElement | HTMLImageElement
if(callback) {
loader.addEventListener('error', callback);
}
return false;
}
}

60
src/lib/appManagers/appProfileManager.ts

@ -512,9 +512,10 @@ export class AppProfileManager { @@ -512,9 +512,10 @@ export class AppProfileManager {
return {cached, loadPromise: getAvatarPromise};
}
public putAvatar(div: HTMLElement, peerId: number, photo: UserProfilePhoto.userProfilePhoto | ChatPhoto.chatPhoto, size: PeerPhotoSize, img = new Image()) {
const {cached, loadPromise} = this.loadAvatar(peerId, photo, size);
public putAvatar(div: HTMLElement, peerId: number, photo: UserProfilePhoto.userProfilePhoto | ChatPhoto.chatPhoto, size: PeerPhotoSize, img = new Image(), onlyThumb = false) {
let {cached, loadPromise} = this.loadAvatar(peerId, photo, size);
let renderThumbPromise: Promise<void>;
let callback: () => void;
if(cached) {
// смотри в misc.ts: renderImageFromUrl
@ -528,41 +529,52 @@ export class AppProfileManager { @@ -528,41 +529,52 @@ export class AppProfileManager {
img.classList.add('fade-in');
}
let thumbImage: HTMLImageElement;
if(photo.stripped_thumb) {
thumbImage = new Image();
div.classList.add('avatar-relative');
thumbImage.classList.add('avatar-photo', 'avatar-photo-thumbnail');
img.classList.add('avatar-photo');
const url = appPhotosManager.getPreviewURLFromBytes(photo.stripped_thumb);
renderThumbPromise = renderImageFromUrl(thumbImage, url).then(() => {
replaceContent(div, thumbImage);
});
}
callback = () => {
replaceContent(div, img);
if(photo.stripped_thumb) {
div.append(img);
} else {
replaceContent(div, img);
}
setTimeout(() => {
if(div.childElementCount) {
div.dataset.color = '';
if(animate) {
sequentialDom.mutateElement(img, () => {
sequentialDom.mutateElement(img, () => {
div.dataset.color = '';
if(animate) {
img.classList.remove('fade-in');
});
}
}
if(thumbImage) {
thumbImage.remove();
}
});
}
}, animate ? 200 : 0);
};
}
const renderPromise = loadPromise.then((url) => {
/* if(photo.stripped_thumb) {
url = appPhotosManager.getPreviewURLFromBytes(photo.stripped_thumb);
} */
return new Promise<void>((resolve) => {
renderImageFromUrl(img, url, () => {
callback();
resolve();
}/* , false */);
});
});
const renderPromise = loadPromise
.then((url) => renderImageFromUrl(img, url/* , false */))
.then(() => callback());
return {cached, loadPromise: renderPromise};
return {cached, loadPromise: renderThumbPromise || renderPromise};
}
// peerId === peerId || title
public putPhoto(div: HTMLElement, peerId: number, isDialog = false, title = '') {
public putPhoto(div: HTMLElement, peerId: number, isDialog = false, title = '', onlyThumb = false) {
const photo = appPeersManager.getPeerPhoto(peerId);
const size: PeerPhotoSize = 'photo_small';
@ -614,7 +626,7 @@ export class AppProfileManager { @@ -614,7 +626,7 @@ export class AppProfileManager {
}
if(avatarAvailable/* && false */) {
return this.putAvatar(div, peerId, photo, size);
return this.putAvatar(div, peerId, photo, size, undefined, onlyThumb);
}
}
}

10
src/scss/partials/_avatar.scss

@ -124,6 +124,10 @@ avatar-element { @@ -124,6 +124,10 @@ avatar-element {
cursor: pointer;
}
&.avatar-relative {
position: relative;
}
/* &.avatar-54 {
width: 54px;
height: 54px;
@ -198,3 +202,9 @@ avatar-element { @@ -198,3 +202,9 @@ avatar-element {
--multiplier: 3.375;
}
}
.avatar-photo {
position: absolute;
top: 0;
left: 0;
}

Loading…
Cancel
Save