show placeholders for loading img tags, this allows the entry to have its final height immediately

This commit is contained in:
Athou
2022-08-20 23:02:55 +02:00
parent 1f2a265c54
commit f81491fb32
10 changed files with 155 additions and 34 deletions

View File

@@ -1,4 +1,8 @@
import { createStyles, Text, TypographyStylesProvider } from "@mantine/core"
import { Box, createStyles, TypographyStylesProvider } from "@mantine/core"
import { Constants } from "app/constants"
import { calculatePlaceholderSize } from "app/utils"
import { ImageWithPlaceholderWhileLoading } from "components/ImageWithPlaceholderWhileLoading"
import { Interweave, TransformCallback } from "interweave"
export interface ContentProps {
content: string
@@ -11,10 +15,6 @@ const useStyles = createStyles(theme => ({
"& a": {
color: theme.fn.variant({ color: theme.primaryColor, variant: "subtle" }).color,
},
"& img": {
maxWidth: "100%",
height: "auto",
},
"& iframe": {
maxWidth: "100%",
},
@@ -24,11 +24,42 @@ const useStyles = createStyles(theme => ({
},
}))
const transform: TransformCallback = node => {
if (node.tagName === "IMG") {
// show placeholders for loading img tags, this allows the entry to have its final height immediately
const src = node.getAttribute("src") ?? undefined
const alt = node.getAttribute("alt") ?? undefined
const title = node.getAttribute("title") ?? undefined
const width = node.getAttribute("width") ? parseInt(node.getAttribute("width")!, 10) : undefined
const height = node.getAttribute("height") ? parseInt(node.getAttribute("height")!, 10) : undefined
const placeholderSize = calculatePlaceholderSize({
width,
height,
maxWidth: Constants.layout.entryMaxWidth,
})
return (
<ImageWithPlaceholderWhileLoading
src={src}
alt={alt}
title={title}
width={width}
height="auto"
placeholderWidth={placeholderSize.width}
placeholderHeight={placeholderSize.height}
/>
)
}
return undefined
}
export function Content(props: ContentProps) {
const { classes } = useStyles()
return (
<TypographyStylesProvider>
<Text size="md" className={classes.content} dangerouslySetInnerHTML={{ __html: props.content }} />
<Box className={classes.content}>
<Interweave content={props.content} transform={transform} />
</Box>
</TypographyStylesProvider>
)
}