From 8308879ff84d09a777dfc4e2486942d37161ee3f Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 29 Apr 2021 11:29:25 +1000 Subject: [PATCH] add display of roomPreview image on joinableDefaultRooms --- ts/components/Avatar.tsx | 14 ++++++---- ts/components/basic/PillContainer.tsx | 1 + .../session/SessionJoinableDefaultRooms.tsx | 28 +++++++++++++++++-- ts/opengroup/opengroupV2/ApiUtil.ts | 5 +--- ts/opengroup/opengroupV2/OpenGroupAPIV2.ts | 9 ++++-- 5 files changed, 44 insertions(+), 13 deletions(-) diff --git a/ts/components/Avatar.tsx b/ts/components/Avatar.tsx index 8d7eea7db..95ea9d5e1 100644 --- a/ts/components/Avatar.tsx +++ b/ts/components/Avatar.tsx @@ -19,6 +19,7 @@ type Props = { name?: string; // display name, profileName or phoneNumber, whatever is set first pubkey?: string; size: AvatarSize; + base64Data?: string; // if this is not empty, it will be used to render the avatar with base64 encoded data memberAvatars?: Array; // this is added by usingClosedConversationDetails onAvatarClick?: () => void; }; @@ -55,27 +56,29 @@ const NoImage = (props: { const AvatarImage = (props: { avatarPath?: string; + base64Data?: string; name?: string; // display name, profileName or phoneNumber, whatever is set first imageBroken: boolean; handleImageError: () => any; }) => { - const { avatarPath, name, imageBroken, handleImageError } = props; + const { avatarPath, base64Data, name, imageBroken, handleImageError } = props; - if (!avatarPath || imageBroken) { + if ((!avatarPath && !base64Data) || imageBroken) { return null; } + const dataToDisplay = base64Data ? `data:image/jpeg;base64,${base64Data}` : avatarPath; return ( {window.i18n('contactAvatarAlt', ); }; export const Avatar = (props: Props) => { - const { avatarPath, size, memberAvatars, name } = props; + const { avatarPath, base64Data, size, memberAvatars, name } = props; const [imageBroken, setImageBroken] = useState(false); // contentType is not important @@ -86,7 +89,7 @@ export const Avatar = (props: Props) => { }; const isClosedGroupAvatar = memberAvatars && memberAvatars.length; - const hasImage = urlToLoad && !imageBroken && !isClosedGroupAvatar; + const hasImage = (base64Data || urlToLoad) && !imageBroken && !isClosedGroupAvatar; const isClickable = !!props.onAvatarClick; @@ -107,6 +110,7 @@ export const Avatar = (props: Props) => { {hasImage ? ( ` padding: ${props => props.padding || ''}; margin: ${props => props.margin || ''}; border-radius: 300px; + cursor: pointer; border: 1px solid ${props => props.theme.colors.pillDividerColor}; transition: ${props => props.theme.common.animations.defaultDuration}; &:hover { diff --git a/ts/components/session/SessionJoinableDefaultRooms.tsx b/ts/components/session/SessionJoinableDefaultRooms.tsx index 5bcbd935b..db150d1a6 100644 --- a/ts/components/session/SessionJoinableDefaultRooms.tsx +++ b/ts/components/session/SessionJoinableDefaultRooms.tsx @@ -1,6 +1,10 @@ -import React, { useReducer } from 'react'; +import React, { useEffect, useReducer, useState } from 'react'; import { useSelector } from 'react-redux'; -import { joinOpenGroupV2WithUIEvents } from '../../opengroup/opengroupV2/JoinOpenGroupV2'; +import { + joinOpenGroupV2WithUIEvents, + parseOpenGroupV2, +} from '../../opengroup/opengroupV2/JoinOpenGroupV2'; +import { downloadPreviewOpenGroupV2 } from '../../opengroup/opengroupV2/OpenGroupAPIV2'; import { StateType } from '../../state/reducer'; import { Avatar, AvatarSize } from '../Avatar'; import { Flex } from '../basic/Flex'; @@ -16,9 +20,29 @@ export type JoinableRoomProps = { }; const SessionJoinableRoomAvatar = (props: JoinableRoomProps) => { + const [base64Data, setBase64Data] = useState(''); + + useEffect(() => { + try { + const parsedInfos = parseOpenGroupV2(props.completeUrl); + if (parsedInfos) { + void downloadPreviewOpenGroupV2(parsedInfos) + .then(base64 => { + setBase64Data(base64 || ''); + }) + .catch(e => { + window.log.warn('downloadPreviewOpenGroupV2 failed', e); + setBase64Data(''); + }); + } + } catch (e) { + console.warn(e); + } + }, [props.imageId, props.completeUrl]); return ( props.onClick(props.completeUrl)} /> diff --git a/ts/opengroup/opengroupV2/ApiUtil.ts b/ts/opengroup/opengroupV2/ApiUtil.ts index 6e12b43c6..2381ee349 100644 --- a/ts/opengroup/opengroupV2/ApiUtil.ts +++ b/ts/opengroup/opengroupV2/ApiUtil.ts @@ -41,11 +41,8 @@ export type OpenGroupV2Info = { imageId?: string; }; -export type OpenGroupV2InfoJoinable = { - id: string; - name: string; +export type OpenGroupV2InfoJoinable = OpenGroupV2Info & { completeUrl: string; - imageId?: string; }; /** diff --git a/ts/opengroup/opengroupV2/OpenGroupAPIV2.ts b/ts/opengroup/opengroupV2/OpenGroupAPIV2.ts index ca592d401..e688e0533 100644 --- a/ts/opengroup/opengroupV2/OpenGroupAPIV2.ts +++ b/ts/opengroup/opengroupV2/OpenGroupAPIV2.ts @@ -529,9 +529,14 @@ export const downloadFileOpenGroupV2ByUrl = async ( return new Uint8Array(fromBase64ToArrayBuffer(base64Data)); }; +/** + * Download the preview image for that opengroup room. + * The returned value is a base64 string. + * It can be used directly, or saved on the attachments directory if needed, but this function does not handle it + */ export const downloadPreviewOpenGroupV2 = async ( roomInfos: OpenGroupRequestCommonType -): Promise => { +): Promise => { const request: OpenGroupV2Request = { method: 'GET', room: roomInfos.roomId, @@ -552,7 +557,7 @@ export const downloadPreviewOpenGroupV2 = async ( if (!base64Data) { return null; } - return new Uint8Array(fromBase64ToArrayBuffer(base64Data)); + return base64Data; }; /**