From 0322c169ace3e2529b8bb23264c9b936ee0d68e2 Mon Sep 17 00:00:00 2001 From: billsonnn Date: Tue, 26 Mar 2024 19:49:08 -0400 Subject: [PATCH] Fix memory leak with avatar image --- src/api/room/widgets/ChatBubbleUtilities.ts | 8 ++-- src/common/layout/LayoutAvatarImageView.tsx | 53 +++++++++++---------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/api/room/widgets/ChatBubbleUtilities.ts b/src/api/room/widgets/ChatBubbleUtilities.ts index c31fa2f9..9e1df0f4 100644 --- a/src/api/room/widgets/ChatBubbleUtilities.ts +++ b/src/api/room/widgets/ChatBubbleUtilities.ts @@ -25,17 +25,17 @@ export class ChatBubbleUtilities figure = avatarImage.getFigure().getFigureString(); - const image = await avatarImage.getCroppedImage(AvatarSetType.HEAD); + const imageUrl = await avatarImage.getCroppedImageUrl(AvatarSetType.HEAD); const color = avatarImage.getPartColor(AvatarFigurePartType.CHEST); - if(isPlaceholder) this.placeHolderImageUrl = image.src; + if(isPlaceholder) this.placeHolderImageUrl = imageUrl; this.AVATAR_COLOR_CACHE.set(figure, ((color && color.rgb) || 16777215)); - this.AVATAR_IMAGE_CACHE.set(figure, image.src); + this.AVATAR_IMAGE_CACHE.set(figure, imageUrl); avatarImage.dispose(); - return image.src; + return imageUrl; } public static async getUserImage(figure: string): Promise diff --git a/src/common/layout/LayoutAvatarImageView.tsx b/src/common/layout/LayoutAvatarImageView.tsx index d73736eb..d3902769 100644 --- a/src/common/layout/LayoutAvatarImageView.tsx +++ b/src/common/layout/LayoutAvatarImageView.tsx @@ -15,7 +15,7 @@ export const LayoutAvatarImageView: FC = props => { const { figure = '', gender = 'M', headOnly = false, direction = 0, scale = 1, classNames = [], style = {}, ...rest } = props; const [ avatarUrl, setAvatarUrl ] = useState(null); - const [ randomValue, setRandomValue ] = useState(-1); + const [ isReady, setIsReady ] = useState(false); const isDisposed = useRef(false); const getClassNames = useMemo(() => @@ -47,39 +47,40 @@ export const LayoutAvatarImageView: FC = props => useEffect(() => { - const avatarImage = GetAvatarRenderManager().createAvatarImage(figure, AvatarScaleType.LARGE, gender, { - resetFigure: figure => - { - if(isDisposed.current) return; + if(!isReady) return; - setRandomValue(Math.random()); - }, - dispose: () => - {}, - disposed: false - }, null); - - if(!avatarImage) return; - - let setType = AvatarSetType.FULL; - - if(headOnly) setType = AvatarSetType.HEAD; - - avatarImage.setDirection(setType, direction); - - (async () => + const resetFigure = (_figure: string) => { - const image = await avatarImage.getCroppedImage(setType); + if(isDisposed.current) return; + + const avatarImage = GetAvatarRenderManager().createAvatarImage(_figure, AvatarScaleType.LARGE, gender, { resetFigure: (figure: string) => resetFigure(figure), dispose: null, disposed: false }); - if(image) setAvatarUrl(image.src); + let setType = AvatarSetType.FULL; - avatarImage.dispose(); - })(); - }, [ figure, gender, direction, headOnly, randomValue ]); + if(headOnly) setType = AvatarSetType.HEAD; + + avatarImage.setDirection(setType, direction); + + const loadImage = async () => + { + const imageUrl = await avatarImage.getCroppedImageUrl(setType); + + if(imageUrl && !isDisposed.current) setAvatarUrl(imageUrl); + + avatarImage.dispose(); + } + + loadImage(); + } + + resetFigure(figure); + }, [ figure, gender, direction, headOnly, isReady ]); useEffect(() => { isDisposed.current = false; + + setIsReady(true); return () => {