You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
5.5 KiB
TypeScript
199 lines
5.5 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
|
|
import styled from 'styled-components';
|
|
import { parseOpenGroupV2 } from '../../../session/apis/open_group_api/opengroupV2/JoinOpenGroupV2';
|
|
import { sogsV3FetchPreviewBase64 } from '../../../session/apis/open_group_api/sogsv3/sogsV3FetchFile';
|
|
import { DefaultRoomsState, updateDefaultBase64RoomData } from '../../../state/ducks/defaultRooms';
|
|
import { StateType } from '../../../state/reducer';
|
|
import { Avatar, AvatarSize } from '../../avatar/Avatar';
|
|
import { Flex } from '../../basic/Flex';
|
|
import { H4 } from '../../basic/Heading';
|
|
import { PillContainerHoverable, StyledPillContainerHoverable } from '../../basic/PillContainer';
|
|
import { SpacerXS } from '../../basic/Text';
|
|
import { SessionSpinner } from '../../loading';
|
|
import { useHTMLDirection } from '../../../util/i18n/rtlSupport';
|
|
import { Localizer } from '../../basic/Localizer';
|
|
|
|
export type JoinableRoomProps = {
|
|
completeUrl: string;
|
|
name: string;
|
|
roomId: string;
|
|
imageId?: string;
|
|
onClick?: (completeUrl: string) => void;
|
|
base64Data?: string;
|
|
};
|
|
|
|
const SessionJoinableRoomAvatar = (props: JoinableRoomProps) => {
|
|
const dispatch = useDispatch();
|
|
|
|
useEffect(() => {
|
|
let isCancelled = false;
|
|
|
|
try {
|
|
const parsedInfos = parseOpenGroupV2(props.completeUrl);
|
|
const imageID = props.imageId;
|
|
if (parsedInfos) {
|
|
if (props.base64Data) {
|
|
return;
|
|
}
|
|
if (isCancelled) {
|
|
return;
|
|
}
|
|
// eslint-disable-next-line more/no-then
|
|
sogsV3FetchPreviewBase64({ ...parsedInfos, imageID })
|
|
.then(base64 => {
|
|
if (isCancelled) {
|
|
return;
|
|
}
|
|
const payload = {
|
|
roomId: props.roomId,
|
|
base64Data: base64 || '',
|
|
};
|
|
dispatch(updateDefaultBase64RoomData(payload));
|
|
})
|
|
.catch(e => {
|
|
if (isCancelled) {
|
|
return;
|
|
}
|
|
window?.log?.warn('sogsV3FetchPreview failed', e);
|
|
const payload = {
|
|
roomId: props.roomId,
|
|
base64Data: '',
|
|
};
|
|
dispatch(updateDefaultBase64RoomData(payload));
|
|
});
|
|
}
|
|
} catch (e) {
|
|
window?.log?.warn(e.message);
|
|
}
|
|
// eslint-disable-next-line consistent-return
|
|
return () => {
|
|
isCancelled = true;
|
|
};
|
|
}, [props.imageId, props.completeUrl, dispatch, props.base64Data, props.roomId]);
|
|
|
|
return (
|
|
<Avatar
|
|
size={AvatarSize.XS}
|
|
base64Data={props.base64Data}
|
|
{...props}
|
|
pubkey=""
|
|
onAvatarClick={() => props.onClick?.(props.completeUrl)}
|
|
/>
|
|
);
|
|
};
|
|
|
|
const StyledRoomName = styled(Flex)`
|
|
font-size: var(--font-size-md);
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
margin: 0 var(--margins-sm);
|
|
`;
|
|
|
|
const SessionJoinableRoomName = (props: JoinableRoomProps) => {
|
|
return <StyledRoomName>{props.name}</StyledRoomName>;
|
|
};
|
|
|
|
const SessionJoinableRoomRow = (props: JoinableRoomProps) => {
|
|
const { onClick, completeUrl } = props;
|
|
const onClickWithUrl = onClick
|
|
? () => {
|
|
onClick?.(completeUrl);
|
|
}
|
|
: undefined;
|
|
|
|
return (
|
|
<StyledPillContainerHoverable container={true} alignItems="center" flexShrink={0} width={'70%'}>
|
|
<PillContainerHoverable
|
|
onClick={onClickWithUrl}
|
|
margin={'var(--margins-sm)'}
|
|
padding="var(--margins-xs) var(--margins-sm)"
|
|
>
|
|
<SessionJoinableRoomAvatar {...props} />
|
|
<SessionJoinableRoomName {...props} />
|
|
</PillContainerHoverable>
|
|
</StyledPillContainerHoverable>
|
|
);
|
|
};
|
|
|
|
const JoinableRooms = (props: {
|
|
joinableRooms: DefaultRoomsState;
|
|
alreadyJoining: boolean;
|
|
onJoinClick?: (completeUrl: string) => void;
|
|
}) => {
|
|
return (
|
|
<>
|
|
{props.joinableRooms.rooms.map(r => {
|
|
return (
|
|
<SessionJoinableRoomRow
|
|
key={r.id}
|
|
completeUrl={r.completeUrl}
|
|
name={r.name}
|
|
roomId={r.id}
|
|
imageId={r.imageId}
|
|
base64Data={r.base64Data}
|
|
onClick={props.onJoinClick}
|
|
/>
|
|
);
|
|
})}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export const SessionJoinableRooms = (props: {
|
|
onJoinClick?: (completeUrl: string) => void;
|
|
alreadyJoining: boolean;
|
|
}) => {
|
|
const htmlDirection = useHTMLDirection();
|
|
const joinableRooms = useSelector((state: StateType) => state.defaultRooms);
|
|
|
|
if (!joinableRooms.inProgress && !joinableRooms.rooms?.length) {
|
|
window?.log?.info('no default joinable rooms yet and not in progress');
|
|
return null;
|
|
}
|
|
|
|
// There is a spinner in the overlay, so we don't need to show it when joining
|
|
if (props.alreadyJoining) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<Flex
|
|
container={true}
|
|
flexGrow={1}
|
|
flexDirection="column"
|
|
alignItems="center"
|
|
dir={htmlDirection}
|
|
width="100%"
|
|
>
|
|
<H4>
|
|
<Localizer token="communityJoinOfficial" />
|
|
</H4>
|
|
<SpacerXS />
|
|
<Flex
|
|
container={true}
|
|
flexDirection="column"
|
|
justifyContent="center"
|
|
alignItems="center"
|
|
flexGrow={0}
|
|
flexWrap="wrap"
|
|
dir={htmlDirection}
|
|
width={'100%'}
|
|
margin={'0 0 0 calc(var(--margins-md) * -1)'}
|
|
>
|
|
{joinableRooms.inProgress ? (
|
|
<SessionSpinner loading={true} />
|
|
) : (
|
|
<JoinableRooms
|
|
joinableRooms={joinableRooms}
|
|
alreadyJoining={props.alreadyJoining}
|
|
onJoinClick={props.onJoinClick}
|
|
/>
|
|
)}
|
|
</Flex>
|
|
</Flex>
|
|
);
|
|
};
|