Avatar: Get rid of data-uri avatars
This commit is contained in:
parent
77194245de
commit
09caf525a3
@ -14,7 +14,6 @@ import {
|
|||||||
} from '../../../config';
|
} from '../../../config';
|
||||||
import localDb from '../localDb';
|
import localDb from '../localDb';
|
||||||
import { getEntityTypeById } from '../gramjsBuilders';
|
import { getEntityTypeById } from '../gramjsBuilders';
|
||||||
import { blobToDataUri } from '../../../util/files';
|
|
||||||
import * as cacheApi from '../../../util/cacheApi';
|
import * as cacheApi from '../../../util/cacheApi';
|
||||||
|
|
||||||
type EntityType = (
|
type EntityType = (
|
||||||
@ -221,8 +220,6 @@ async function parseMedia(
|
|||||||
data: Buffer, mediaFormat: ApiMediaFormat, mimeType?: string,
|
data: Buffer, mediaFormat: ApiMediaFormat, mimeType?: string,
|
||||||
): Promise<ApiParsedMedia | undefined> {
|
): Promise<ApiParsedMedia | undefined> {
|
||||||
switch (mediaFormat) {
|
switch (mediaFormat) {
|
||||||
case ApiMediaFormat.DataUri:
|
|
||||||
return blobToDataUri(new Blob([data], { type: mimeType }));
|
|
||||||
case ApiMediaFormat.BlobUrl:
|
case ApiMediaFormat.BlobUrl:
|
||||||
return new Blob([data], { type: mimeType });
|
return new Blob([data], { type: mimeType });
|
||||||
case ApiMediaFormat.Lottie: {
|
case ApiMediaFormat.Lottie: {
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
// and messages media as Blob for smaller size.
|
// and messages media as Blob for smaller size.
|
||||||
|
|
||||||
export enum ApiMediaFormat {
|
export enum ApiMediaFormat {
|
||||||
DataUri,
|
|
||||||
BlobUrl,
|
BlobUrl,
|
||||||
Lottie,
|
Lottie,
|
||||||
Progressive,
|
Progressive,
|
||||||
|
|||||||
@ -1,12 +1,18 @@
|
|||||||
import { MouseEvent as ReactMouseEvent } from 'react';
|
import { MouseEvent as ReactMouseEvent } from 'react';
|
||||||
import React, { FC, useCallback, memo } from '../../lib/teact/teact';
|
import React, { FC, memo, useCallback } from '../../lib/teact/teact';
|
||||||
|
|
||||||
import { ApiUser, ApiChat, ApiMediaFormat } from '../../api/types';
|
import { ApiChat, ApiMediaFormat, ApiUser } from '../../api/types';
|
||||||
|
|
||||||
import { IS_TEST } from '../../config';
|
import { IS_TEST } from '../../config';
|
||||||
import {
|
import {
|
||||||
getChatAvatarHash, getChatTitle, isChatPrivate,
|
getChatAvatarHash,
|
||||||
getUserFullName, isUserOnline, isDeletedUser, getUserColorKey, isChatWithRepliesBot,
|
getChatTitle,
|
||||||
|
getUserColorKey,
|
||||||
|
getUserFullName,
|
||||||
|
isChatPrivate,
|
||||||
|
isChatWithRepliesBot,
|
||||||
|
isDeletedUser,
|
||||||
|
isUserOnline,
|
||||||
} from '../../modules/helpers';
|
} from '../../modules/helpers';
|
||||||
import { getFirstLetters } from '../../util/textFormat';
|
import { getFirstLetters } from '../../util/textFormat';
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
@ -52,8 +58,8 @@ const Avatar: FC<OwnProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataUri = useMedia(imageHash, false, ApiMediaFormat.DataUri, lastSyncTime);
|
const blobUrl = useMedia(imageHash, false, ApiMediaFormat.BlobUrl, lastSyncTime);
|
||||||
const { shouldRenderFullMedia, transitionClassNames } = useTransitionForMedia(dataUri, 'slow');
|
const { shouldRenderFullMedia, transitionClassNames } = useTransitionForMedia(blobUrl, 'slow');
|
||||||
|
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
|
|
||||||
@ -66,7 +72,7 @@ const Avatar: FC<OwnProps> = ({
|
|||||||
} else if (isReplies) {
|
} else if (isReplies) {
|
||||||
content = <i className="icon-reply-filled" />;
|
content = <i className="icon-reply-filled" />;
|
||||||
} else if (shouldRenderFullMedia) {
|
} else if (shouldRenderFullMedia) {
|
||||||
content = <img src={dataUri} className={`${transitionClassNames} avatar-media`} alt="" decoding="async" />;
|
content = <img src={blobUrl} className={`${transitionClassNames} avatar-media`} alt="" decoding="async" />;
|
||||||
} else if (user) {
|
} else if (user) {
|
||||||
const userFullName = getUserFullName(user);
|
const userFullName = getUserFullName(user);
|
||||||
content = userFullName ? getFirstLetters(userFullName, 2) : undefined;
|
content = userFullName ? getFirstLetters(userFullName, 2) : undefined;
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
import React, { FC, memo } from '../../lib/teact/teact';
|
import React, { FC, memo } from '../../lib/teact/teact';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ApiUser, ApiChat, ApiMediaFormat, ApiPhoto,
|
ApiChat, ApiMediaFormat, ApiPhoto, ApiUser,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getChatAvatarHash, isDeletedUser, getUserColorKey, getChatTitle, isChatPrivate, getUserFullName, isChatWithRepliesBot,
|
getChatAvatarHash,
|
||||||
|
getChatTitle,
|
||||||
|
getUserColorKey,
|
||||||
|
getUserFullName,
|
||||||
|
isChatPrivate,
|
||||||
|
isChatWithRepliesBot,
|
||||||
|
isDeletedUser,
|
||||||
} from '../../modules/helpers';
|
} from '../../modules/helpers';
|
||||||
import renderText from './helpers/renderText';
|
import renderText from './helpers/renderText';
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
@ -42,7 +48,7 @@ const ProfilePhoto: FC<OwnProps> = ({
|
|||||||
const isDeleted = user && isDeletedUser(user);
|
const isDeleted = user && isDeletedUser(user);
|
||||||
const isRepliesChat = chat && isChatWithRepliesBot(chat.id);
|
const isRepliesChat = chat && isChatWithRepliesBot(chat.id);
|
||||||
|
|
||||||
function getMediaHash(size: 'normal' | 'big' = 'big', forceAvatar?: boolean) {
|
function getMediaHash(size: 'normal' | 'big', forceAvatar?: boolean) {
|
||||||
if (photo && !forceAvatar) {
|
if (photo && !forceAvatar) {
|
||||||
return `photo${photo.id}?size=c`;
|
return `photo${photo.id}?size=c`;
|
||||||
}
|
}
|
||||||
@ -59,21 +65,11 @@ const ProfilePhoto: FC<OwnProps> = ({
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageHash = getMediaHash();
|
const photoBlobUrl = useMedia(getMediaHash('big'), false, ApiMediaFormat.BlobUrl, lastSyncTime);
|
||||||
const fullMediaData = useMedia(
|
const avatarMediaHash = isFirstPhoto && !photoBlobUrl ? getMediaHash('normal', true) : undefined;
|
||||||
imageHash,
|
const avatarBlobUrl = useMedia(avatarMediaHash, false, ApiMediaFormat.BlobUrl, lastSyncTime);
|
||||||
false,
|
const thumbDataUri = useBlurSync(!photoBlobUrl && photo && photo.thumbnail && photo.thumbnail.dataUri);
|
||||||
imageHash?.startsWith('avatar') ? ApiMediaFormat.DataUri : ApiMediaFormat.BlobUrl,
|
const imageSrc = photoBlobUrl || avatarBlobUrl || thumbDataUri;
|
||||||
lastSyncTime,
|
|
||||||
);
|
|
||||||
const avatarThumbnailData = useMedia(
|
|
||||||
!fullMediaData && isFirstPhoto ? getMediaHash('normal', true) : undefined,
|
|
||||||
false,
|
|
||||||
ApiMediaFormat.DataUri,
|
|
||||||
lastSyncTime,
|
|
||||||
);
|
|
||||||
const thumbDataUri = useBlurSync(!fullMediaData && photo && photo.thumbnail && photo.thumbnail.dataUri);
|
|
||||||
const imageSrc = fullMediaData || avatarThumbnailData || thumbDataUri;
|
|
||||||
const prevImageSrc = usePrevious(imageSrc);
|
const prevImageSrc = usePrevious(imageSrc);
|
||||||
|
|
||||||
let content: string | undefined = '';
|
let content: string | undefined = '';
|
||||||
|
|||||||
@ -57,7 +57,7 @@ function preloadAvatars() {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mediaLoader.fetch(avatarHash, ApiMediaFormat.DataUri);
|
return mediaLoader.fetch(avatarHash, ApiMediaFormat.BlobUrl);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -36,11 +36,7 @@ const WallpaperTile: FC<OwnProps> = ({
|
|||||||
const localMediaHash = `wallpaper${document.id!}`;
|
const localMediaHash = `wallpaper${document.id!}`;
|
||||||
const localBlobUrl = document.previewBlobUrl;
|
const localBlobUrl = document.previewBlobUrl;
|
||||||
const previewBlobUrl = useMedia(`${localMediaHash}?size=m`);
|
const previewBlobUrl = useMedia(`${localMediaHash}?size=m`);
|
||||||
const thumbRef = useCanvasBlur(
|
const thumbRef = useCanvasBlur(document.thumbnail?.dataUri, Boolean(previewBlobUrl), true);
|
||||||
document.thumbnail?.dataUri,
|
|
||||||
Boolean(previewBlobUrl),
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
const {
|
const {
|
||||||
shouldRenderThumb, shouldRenderFullMedia, transitionClassNames,
|
shouldRenderThumb, shouldRenderFullMedia, transitionClassNames,
|
||||||
} = useTransitionForMedia(previewBlobUrl || localBlobUrl, 'slow');
|
} = useTransitionForMedia(previewBlobUrl || localBlobUrl, 'slow');
|
||||||
|
|||||||
@ -166,7 +166,7 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
|
|||||||
return message && getMessageMediaHash(message, isFull ? 'viewerFull' : 'viewerPreview');
|
return message && getMessageMediaHash(message, isFull ? 'viewerFull' : 'viewerPreview');
|
||||||
}
|
}
|
||||||
|
|
||||||
const blobUrlPictogram = useMedia(
|
const pictogramBlobUrl = useMedia(
|
||||||
message && (isFromSharedMedia || isFromSearch) && getMessageMediaHash(message, 'pictogram'),
|
message && (isFromSharedMedia || isFromSearch) && getMessageMediaHash(message, 'pictogram'),
|
||||||
undefined,
|
undefined,
|
||||||
ApiMediaFormat.BlobUrl,
|
ApiMediaFormat.BlobUrl,
|
||||||
@ -174,16 +174,14 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
|
|||||||
isGhostAnimation && ANIMATION_DURATION,
|
isGhostAnimation && ANIMATION_DURATION,
|
||||||
);
|
);
|
||||||
const previewMediaHash = getMediaHash();
|
const previewMediaHash = getMediaHash();
|
||||||
const blobUrlPreview = useMedia(
|
const previewBlobUrl = useMedia(
|
||||||
previewMediaHash,
|
previewMediaHash,
|
||||||
undefined,
|
undefined,
|
||||||
isAvatar && previewMediaHash && previewMediaHash.startsWith('profilePhoto')
|
ApiMediaFormat.BlobUrl,
|
||||||
? ApiMediaFormat.DataUri
|
|
||||||
: ApiMediaFormat.BlobUrl,
|
|
||||||
undefined,
|
undefined,
|
||||||
isGhostAnimation && ANIMATION_DURATION,
|
isGhostAnimation && ANIMATION_DURATION,
|
||||||
);
|
);
|
||||||
const { mediaData: fullMediaData, downloadProgress } = useMediaWithDownloadProgress(
|
const { mediaData: fullMediaBlobUrl, downloadProgress } = useMediaWithDownloadProgress(
|
||||||
getMediaHash(true),
|
getMediaHash(true),
|
||||||
undefined,
|
undefined,
|
||||||
message && getMessageMediaFormat(message, 'viewerFull'),
|
message && getMessageMediaFormat(message, 'viewerFull'),
|
||||||
@ -192,7 +190,7 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const localBlobUrl = (photo || video) ? (photo || video)!.blobUrl : undefined;
|
const localBlobUrl = (photo || video) ? (photo || video)!.blobUrl : undefined;
|
||||||
let bestImageData = (!isVideo && (localBlobUrl || fullMediaData)) || blobUrlPreview || blobUrlPictogram;
|
let bestImageData = (!isVideo && (localBlobUrl || fullMediaBlobUrl)) || previewBlobUrl || pictogramBlobUrl;
|
||||||
const thumbDataUri = useBlurSync(!bestImageData && message && getMessageMediaThumbDataUri(message));
|
const thumbDataUri = useBlurSync(!bestImageData && message && getMessageMediaThumbDataUri(message));
|
||||||
if (!bestImageData && origin !== MediaViewerOrigin.SearchResult) {
|
if (!bestImageData && origin !== MediaViewerOrigin.SearchResult) {
|
||||||
bestImageData = thumbDataUri;
|
bestImageData = thumbDataUri;
|
||||||
@ -459,7 +457,7 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
|
|||||||
return (
|
return (
|
||||||
<div key={chatId} className="media-viewer-content">
|
<div key={chatId} className="media-viewer-content">
|
||||||
{renderPhoto(
|
{renderPhoto(
|
||||||
fullMediaData || blobUrlPreview,
|
fullMediaBlobUrl || previewBlobUrl,
|
||||||
calculateMediaViewerDimensions(AVATAR_FULL_DIMENSIONS, false),
|
calculateMediaViewerDimensions(AVATAR_FULL_DIMENSIONS, false),
|
||||||
!IS_SINGLE_COLUMN_LAYOUT && !isZoomed,
|
!IS_SINGLE_COLUMN_LAYOUT && !isZoomed,
|
||||||
)}
|
)}
|
||||||
@ -476,14 +474,14 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
|
|||||||
onClick={handleToggleFooterVisibility}
|
onClick={handleToggleFooterVisibility}
|
||||||
>
|
>
|
||||||
{isPhoto && renderPhoto(
|
{isPhoto && renderPhoto(
|
||||||
localBlobUrl || fullMediaData || blobUrlPreview || blobUrlPictogram,
|
localBlobUrl || fullMediaBlobUrl || previewBlobUrl || pictogramBlobUrl,
|
||||||
message && calculateMediaViewerDimensions(dimensions!, hasFooter),
|
message && calculateMediaViewerDimensions(dimensions!, hasFooter),
|
||||||
!IS_SINGLE_COLUMN_LAYOUT && !isZoomed,
|
!IS_SINGLE_COLUMN_LAYOUT && !isZoomed,
|
||||||
)}
|
)}
|
||||||
{isVideo && (
|
{isVideo && (
|
||||||
<VideoPlayer
|
<VideoPlayer
|
||||||
key={messageId}
|
key={messageId}
|
||||||
url={localBlobUrl || fullMediaData}
|
url={localBlobUrl || fullMediaBlobUrl}
|
||||||
isGif={isGif}
|
isGif={isGif}
|
||||||
posterData={bestImageData}
|
posterData={bestImageData}
|
||||||
posterSize={message && calculateMediaViewerDimensions(dimensions!, hasFooter, true)}
|
posterSize={message && calculateMediaViewerDimensions(dimensions!, hasFooter, true)}
|
||||||
@ -550,7 +548,7 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
|
|||||||
{renderSenderInfo}
|
{renderSenderInfo}
|
||||||
</Transition>
|
</Transition>
|
||||||
<MediaViewerActions
|
<MediaViewerActions
|
||||||
mediaData={fullMediaData || blobUrlPreview}
|
mediaData={fullMediaBlobUrl || previewBlobUrl}
|
||||||
isVideo={isVideo}
|
isVideo={isVideo}
|
||||||
isZoomed={isZoomed}
|
isZoomed={isZoomed}
|
||||||
message={message}
|
message={message}
|
||||||
|
|||||||
@ -64,7 +64,7 @@ const MediaResult: FC<OwnProps> = ({
|
|||||||
return (
|
return (
|
||||||
<BaseResult
|
<BaseResult
|
||||||
focus={focus}
|
focus={focus}
|
||||||
thumbUrl={shouldRenderFullMedia ? mediaBlobUrl : (thumbnail?.dataUri) || thumbnailDataUrl}
|
thumbUrl={shouldRenderFullMedia ? mediaBlobUrl : (thumbnail?.dataUri || thumbnailDataUrl)}
|
||||||
transitionClassNames={shouldRenderFullMedia ? transitionClassNames : undefined}
|
transitionClassNames={shouldRenderFullMedia ? transitionClassNames : undefined}
|
||||||
title={title}
|
title={title}
|
||||||
description={description}
|
description={description}
|
||||||
|
|||||||
@ -8,9 +8,9 @@ import { EMPTY_IMAGE_DATA_URI, webpToPngBase64 } from '../util/webpToPng';
|
|||||||
import { getMessageMediaThumbDataUri } from '../modules/helpers';
|
import { getMessageMediaThumbDataUri } from '../modules/helpers';
|
||||||
|
|
||||||
export default function useWebpThumbnail(message?: ApiMessage) {
|
export default function useWebpThumbnail(message?: ApiMessage) {
|
||||||
const thumbnail = message && getMessageMediaThumbDataUri(message);
|
const thumbDataUri = message && getMessageMediaThumbDataUri(message);
|
||||||
const sticker = message?.content?.sticker;
|
const sticker = message?.content?.sticker;
|
||||||
const shouldDecodeThumbnail = thumbnail && sticker && !isWebpSupported() && thumbnail.includes('image/webp');
|
const shouldDecodeThumbnail = thumbDataUri && sticker && !isWebpSupported() && thumbDataUri.includes('image/webp');
|
||||||
const [thumbnailDecoded, setThumbnailDecoded] = useState(EMPTY_IMAGE_DATA_URI);
|
const [thumbnailDecoded, setThumbnailDecoded] = useState(EMPTY_IMAGE_DATA_URI);
|
||||||
const messageId = message?.id;
|
const messageId = message?.id;
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ export default function useWebpThumbnail(message?: ApiMessage) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
webpToPngBase64(`b64-${messageId}`, thumbnail!)
|
webpToPngBase64(`b64-${messageId}`, thumbDataUri!)
|
||||||
.then(setThumbnailDecoded)
|
.then(setThumbnailDecoded)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@ -27,7 +27,7 @@ export default function useWebpThumbnail(message?: ApiMessage) {
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [messageId, shouldDecodeThumbnail, thumbnail]);
|
}, [messageId, shouldDecodeThumbnail, thumbDataUri]);
|
||||||
|
|
||||||
return shouldDecodeThumbnail ? thumbnailDecoded : thumbnail;
|
return shouldDecodeThumbnail ? thumbnailDecoded : thumbDataUri;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,31 +23,38 @@ export async function fetch(
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const contentType = response.headers.get('Content-Type');
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type.Text:
|
case Type.Text:
|
||||||
return await response.text();
|
return await response.text();
|
||||||
case Type.Blob: {
|
case Type.Blob: {
|
||||||
|
// Ignore deprecated data-uri avatars
|
||||||
|
if (key.startsWith('avatar') && contentType && contentType.startsWith('text')) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
|
|
||||||
// Safari does not return correct Content-Type header for webp images.
|
// Safari does not return correct Content-Type header for webp images.
|
||||||
if (key.substr(0, 7) === 'sticker') {
|
if (key.startsWith('sticker')) {
|
||||||
return new Blob([blob], { type: 'image/webp' });
|
return new Blob([blob], { type: 'image/webp' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const shouldRecreate = !blob.type || (!isHtmlAllowed && blob.type.includes('html'));
|
||||||
// iOS Safari fails to preserve `type` in cache
|
// iOS Safari fails to preserve `type` in cache
|
||||||
if (!blob.type) {
|
let resolvedType = blob.type || contentType;
|
||||||
const contentType = response.headers.get('Content-Type');
|
|
||||||
if (contentType) {
|
if (!(shouldRecreate && resolvedType)) {
|
||||||
return new Blob([blob], { type: isHtmlAllowed ? contentType : contentType.replace(/html/gi, '') });
|
return blob;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent HTML-in-video attacks (for files that were cached before fix)
|
// Prevent HTML-in-video attacks (for files that were cached before fix)
|
||||||
if (!isHtmlAllowed && blob.type.includes('html')) {
|
if (!isHtmlAllowed) {
|
||||||
return new Blob([blob], { type: blob.type.replace(/html/gi, '') });
|
resolvedType = resolvedType.replace(/html/gi, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
return blob;
|
return new Blob([blob], { type: resolvedType });
|
||||||
}
|
}
|
||||||
case Type.Json:
|
case Type.Json:
|
||||||
return await response.json();
|
return await response.json();
|
||||||
|
|||||||
@ -17,7 +17,6 @@ import { oggToWav } from './oggToWav';
|
|||||||
import { webpToPng } from './webpToPng';
|
import { webpToPng } from './webpToPng';
|
||||||
|
|
||||||
const asCacheApiType = {
|
const asCacheApiType = {
|
||||||
[ApiMediaFormat.DataUri]: cacheApi.Type.Text,
|
|
||||||
[ApiMediaFormat.BlobUrl]: cacheApi.Type.Blob,
|
[ApiMediaFormat.BlobUrl]: cacheApi.Type.Blob,
|
||||||
[ApiMediaFormat.Lottie]: cacheApi.Type.Json,
|
[ApiMediaFormat.Lottie]: cacheApi.Type.Json,
|
||||||
[ApiMediaFormat.Progressive]: undefined,
|
[ApiMediaFormat.Progressive]: undefined,
|
||||||
@ -82,6 +81,7 @@ async function fetchFromCacheOrRemote(
|
|||||||
if (!MEDIA_CACHE_DISABLED) {
|
if (!MEDIA_CACHE_DISABLED) {
|
||||||
const cacheName = url.startsWith('avatar') ? MEDIA_CACHE_NAME_AVATARS : MEDIA_CACHE_NAME;
|
const cacheName = url.startsWith('avatar') ? MEDIA_CACHE_NAME_AVATARS : MEDIA_CACHE_NAME;
|
||||||
const cached = await cacheApi.fetch(cacheName, url, asCacheApiType[mediaFormat]!, isHtmlAllowed);
|
const cached = await cacheApi.fetch(cacheName, url, asCacheApiType[mediaFormat]!, isHtmlAllowed);
|
||||||
|
|
||||||
if (cached) {
|
if (cached) {
|
||||||
let media = cached;
|
let media = cached;
|
||||||
|
|
||||||
|
|||||||
@ -25,17 +25,17 @@ export async function webpToPng(url: string, blob: Blob): Promise<Blob | undefin
|
|||||||
return createPng({ result, width, height });
|
return createPng({ result, width, height });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function webpToPngBase64(key: string, url: string): Promise<string> {
|
export async function webpToPngBase64(key: string, dataUri: string): Promise<string> {
|
||||||
if (isWebpSupported() || url.substr(0, 15) !== 'data:image/webp') {
|
if (isWebpSupported() || dataUri.substr(0, 15) !== 'data:image/webp') {
|
||||||
return url;
|
return dataUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
initWebpWorker();
|
initWebpWorker();
|
||||||
|
|
||||||
const pngBlob = await webpToPng(key, dataUriToBlob(url));
|
const pngBlob = await webpToPng(key, dataUriToBlob(dataUri));
|
||||||
|
|
||||||
if (!pngBlob) {
|
if (!pngBlob) {
|
||||||
throw new Error(`Can't convert webp to png. Url: ${url}`);
|
throw new Error(`Can't convert webp to png. Url: ${dataUri}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return blobToDataUri(pngBlob);
|
return blobToDataUri(pngBlob);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user