Fallback image for <FileThumbnail>

## Ticket
5457 Create file thumbnail fallback image for odysee

## Approach
Since `background-image` does not invoke an `onerror` event, create a test Image instance to have the `onerror` capability. This technique is used by majority of plugins. No additional fetch is seen with this technique.
This commit is contained in:
infinite-persistence 2021-08-02 20:33:31 +08:00 committed by infinite-persistence
parent 503e5e9b76
commit afe4fee3f3
5 changed files with 20 additions and 3 deletions

View file

@ -52,6 +52,7 @@ YRBL_SAD_IMG_URL=https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-sad/c2d9649
#LOGO_TEXT_LIGHT=https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-sad/c2d9649633d974e5ffb503925e1f17d951f1bd0f/f262dd #LOGO_TEXT_LIGHT=https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-sad/c2d9649633d974e5ffb503925e1f17d951f1bd0f/f262dd
#LOGO_TEXT_DARK=https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-sad/c2d9649633d974e5ffb503925e1f17d951f1bd0f/f262dd #LOGO_TEXT_DARK=https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-sad/c2d9649633d974e5ffb503925e1f17d951f1bd0f/f262dd
#AVATAR_DEFAULT= #AVATAR_DEFAULT=
#MISSING_THUMB_DEFAULT=
#FAVICON= #FAVICON=
# LOCALE # LOCALE

View file

@ -35,6 +35,7 @@ const config = {
LOGO_TEXT_LIGHT: process.env.LOGO_TEXT_LIGHT, LOGO_TEXT_LIGHT: process.env.LOGO_TEXT_LIGHT,
LOGO_TEXT_DARK: process.env.LOGO_TEXT_DARK, LOGO_TEXT_DARK: process.env.LOGO_TEXT_DARK,
AVATAR_DEFAULT: process.env.AVATAR_DEFAULT, AVATAR_DEFAULT: process.env.AVATAR_DEFAULT,
MISSING_THUMB_DEFAULT: process.env.MISSING_THUMB_DEFAULT,
// OG // OG
OG_TITLE_SUFFIX: process.env.OG_TITLE_SUFFIX, OG_TITLE_SUFFIX: process.env.OG_TITLE_SUFFIX,
OG_HOMEPAGE_TITLE: process.env.OG_HOMEPAGE_TITLE, OG_HOMEPAGE_TITLE: process.env.OG_HOMEPAGE_TITLE,

View file

@ -6,14 +6,16 @@ import useLazyLoading from 'effects/use-lazy-loading';
type Props = { type Props = {
thumb: string, thumb: string,
fallback: ?string,
children?: Node, children?: Node,
className?: string, className?: string,
}; };
const Thumb = (props: Props) => { const Thumb = (props: Props) => {
const { thumb, children, className } = props; const { thumb, fallback, children, className } = props;
const thumbnailRef = React.useRef(null); const thumbnailRef = React.useRef(null);
useLazyLoading(thumbnailRef);
useLazyLoading(thumbnailRef, fallback || '');
return ( return (
<div ref={thumbnailRef} data-background-image={thumb} className={classnames('media__thumb', className)}> <div ref={thumbnailRef} data-background-image={thumb} className={classnames('media__thumb', className)}>

View file

@ -4,6 +4,7 @@ import { getThumbnailCdnUrl } from 'util/thumbnail';
import React from 'react'; import React from 'react';
import FreezeframeWrapper from './FreezeframeWrapper'; import FreezeframeWrapper from './FreezeframeWrapper';
import Placeholder from './placeholder.png'; import Placeholder from './placeholder.png';
import { MISSING_THUMB_DEFAULT } from 'config';
import classnames from 'classnames'; import classnames from 'classnames';
import Thumb from './thumb'; import Thumb from './thumb';
@ -42,6 +43,8 @@ function FileThumbnail(props: Props) {
); );
} }
const fallback = MISSING_THUMB_DEFAULT ? getThumbnailCdnUrl({ thumbnail: MISSING_THUMB_DEFAULT }) : undefined;
let url = thumbnail || (hasResolvedClaim ? Placeholder : ''); let url = thumbnail || (hasResolvedClaim ? Placeholder : '');
// @if TARGET='web' // @if TARGET='web'
// Pass image urls through a compression proxy // Pass image urls through a compression proxy
@ -54,7 +57,7 @@ function FileThumbnail(props: Props) {
if (hasResolvedClaim || thumbnailUrl) { if (hasResolvedClaim || thumbnailUrl) {
return ( return (
<Thumb thumb={thumbnailUrl} className={className}> <Thumb thumb={thumbnailUrl} fallback={fallback} className={className}>
{children} {children}
</Thumb> </Thumb>
); );

View file

@ -5,11 +5,13 @@ import React, { useEffect } from 'react';
/** /**
* Helper React hook for lazy loading images * Helper React hook for lazy loading images
* @param elementRef - A React useRef instance to the element to lazy load. * @param elementRef - A React useRef instance to the element to lazy load.
* @param backgroundFallback
* @param yOffsetPx - Number of pixels from the viewport to start loading. * @param yOffsetPx - Number of pixels from the viewport to start loading.
* @param {Array<>} [deps=[]] - The dependencies this lazy-load is reliant on. * @param {Array<>} [deps=[]] - The dependencies this lazy-load is reliant on.
*/ */
export default function useLazyLoading( export default function useLazyLoading(
elementRef: { current: ?ElementRef<any> }, elementRef: { current: ?ElementRef<any> },
backgroundFallback: string = '',
yOffsetPx: number = 500, yOffsetPx: number = 500,
deps: Array<any> = [] deps: Array<any> = []
) { ) {
@ -42,11 +44,19 @@ export default function useLazyLoading(
// $FlowFixMe // $FlowFixMe
target.src = target.dataset.src; target.src = target.dataset.src;
setSrcLoaded(true); setSrcLoaded(true);
// No fallback handling here (clients have access to 'onerror' on the image ref).
return; return;
} }
// useful for lazy loading background images on divs // useful for lazy loading background images on divs
if (target.dataset.backgroundImage) { if (target.dataset.backgroundImage) {
if (backgroundFallback) {
const tmpImage = new Image();
tmpImage.onerror = () => {
target.style.backgroundImage = `url(${backgroundFallback})`;
};
tmpImage.src = target.dataset.backgroundImage;
}
target.style.backgroundImage = `url(${target.dataset.backgroundImage})`; target.style.backgroundImage = `url(${target.dataset.backgroundImage})`;
} }
} }