Skip to content

Commit

Permalink
chore: add file viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
bang9 committed Sep 6, 2024
1 parent a75b09a commit 4e7d98e
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 37 deletions.
2 changes: 1 addition & 1 deletion packages/uikit
5 changes: 2 additions & 3 deletions src/components/BotMessageWithBodyInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,14 @@ export default function BotMessageWithBodyInput(props: Props) {
const nonChainedMessage = chainTop == null && chainBottom == null;
const displaySender = nonChainedMessage || chainTop;
const displayProfileImage = nonChainedMessage || chainBottom;
const { profileUrl, nickname } = botStudioEditProps?.botInfo ?? {};
const botProfileUrl = profileUrl ?? botUser?.profileUrl;
const { nickname } = botStudioEditProps?.botInfo ?? {};
const botNickname = nickname ?? botUser?.nickname;

return (
<Root>
{displayProfileImage ? (
<div style={{ paddingBottom: profilePaddingBottom }}>
<BotProfileImage size={28} profileUrl={botProfileUrl} />
<BotProfileImage size={28} />
</div>
) : (
<EmptyImageContainer />
Expand Down
10 changes: 8 additions & 2 deletions src/components/BotProfileImage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { styled } from '@linaria/react';
import { useTheme } from 'styled-components';

import { useChatContext } from './chat/context/ChatProvider';
import { getColorBasedOnSaturation } from '../colors';
import { useConstantState } from '../context/ConstantContext';
import BotProfileIcon from '../icons/bot-profile-image-small.svg';

const Container = styled.span<{ backgroundColor: string; size: number }>`
Expand All @@ -23,13 +25,17 @@ const Icon = styled(BotProfileIcon)<{ fill: string }>`
`;

type Props = {
profileUrl?: string;
size: number;
};

function BotProfileImage({ size, profileUrl }: Props) {
function BotProfileImage({ size }: Props) {
const theme = useTheme();

const { botStudioEditProps } = useConstantState();
const { botUser } = useChatContext();
const { botInfo } = botStudioEditProps ?? {};
const profileUrl = botInfo?.profileUrl ?? botUser?.profileUrl;

if (profileUrl) {
return <img src={profileUrl} style={{ borderRadius: '50%', width: size, height: size }} alt={'bot profile'} />;
}
Expand Down
6 changes: 2 additions & 4 deletions src/components/CustomMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,10 @@ type Props = {
export default function CustomMessage(props: Props) {
const { botUser } = useChatContext();
const { message, activeSpinnerId } = props;
const { replacementTextList, enableEmojiFeedback, botStudioEditProps = {} } = useConstantState();
const { replacementTextList, enableEmojiFeedback } = useConstantState();
const { userId: currentUserId } = useWidgetSession();
const { botInfo } = botStudioEditProps;

const botUserId = botUser?.userId;
const botProfileUrl = botInfo?.profileUrl ?? botUser?.profileUrl ?? '';
const isWaitingForBotReply = activeSpinnerId === message.messageId && !!botUser;

const shouldRenderFeedback = () => {
Expand Down Expand Up @@ -103,7 +101,7 @@ export default function CustomMessage(props: Props) {
<BotMessageWithBodyInput
wideContainer={isVideoMessage(message)}
{...props}
bodyComponent={<FileMessage message={message} profileUrl={botProfileUrl} />}
bodyComponent={<FileMessage message={message} />}
createdAt={message.createdAt}
messageFeedback={renderFeedbackButtons()}
/>
Expand Down
10 changes: 1 addition & 9 deletions src/components/CustomTypingIndicatorBubble.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
import BotProfileImage from './BotProfileImage';
import { useChatContext } from './chat/context/ChatProvider';
import { useConstantState } from '../context/ConstantContext';
import { TypingBubble } from '../foundation/components/TypingBubble';

function CustomTypingIndicatorBubble() {
const { botStudioEditProps = {} } = useConstantState();
const { botUser } = useChatContext();

const botInfo = botStudioEditProps.botInfo;
const botProfileUrl = botInfo?.profileUrl ?? botUser?.profileUrl;

return (
<div style={{ display: 'flex', alignItems: 'flex-end', gap: 8, marginTop: 16 }}>
<BotProfileImage size={28} profileUrl={botProfileUrl} />
<BotProfileImage size={28} />
<TypingBubble />
</div>
);
Expand Down
14 changes: 3 additions & 11 deletions src/components/FileMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@ import '../css/index.css';
import { FileMessage as ChatFileMessage } from '@sendbird/chat/message';
import { useState } from 'react';

import FileViewer from '@uikit/modules/GroupChannel/components/FileViewer';
import { isImageMessage, isVideoMessage } from '@uikit/utils';

import BotProfileImage from './BotProfileImage';
import { useChatContext } from './chat/context/ChatProvider';
import { FileViewer } from './ui/FileViewer';

type Props = {
message: ChatFileMessage;
profileUrl: string;
};

export default function FileMessage(props: Props) {
const { message, profileUrl } = props;
const { message } = props;
const { scrollSource } = useChatContext();
const [showFileViewer, setShowFileViewer] = useState(false);

Expand Down Expand Up @@ -42,13 +40,7 @@ export default function FileMessage(props: Props) {
onClick={() => setShowFileViewer(true)}
/>
)}
{showFileViewer && (
<FileViewer
message={message}
onCancel={() => setShowFileViewer(false)}
profile={<BotProfileImage size={32} profileUrl={profileUrl} />}
/>
)}
{showFileViewer && <FileViewer message={message} onClose={() => setShowFileViewer(false)} />}
</div>
);
}
3 changes: 1 addition & 2 deletions src/components/chat/ui/ChatHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export const ChatHeader = ({ fullscreen }: Props) => {

const { botInfo } = botStudioEditProps ?? {};
const botNickname = botInfo?.nickname ?? botUser?.nickname;
const profileUrl = botInfo?.profileUrl ?? botUser?.profileUrl;
const buttonSize = isMobileView ? 24 : 16;
const isExpandableMode = !fullscreen && !isMobileView;

Expand All @@ -43,7 +42,7 @@ export const ChatHeader = ({ fullscreen }: Props) => {
return (
<div className={container}>
<div style={{ marginRight: 6 }}>
<BotProfileImage size={34} profileUrl={profileUrl} />
<BotProfileImage size={34} />
</div>
<div className={headerCenter}>
<Label type={'h2'} color={'onbackground1'} className={titleInline}>
Expand Down
1 change: 1 addition & 0 deletions src/components/chat/ui/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useBlockWhileBotResponding } from '../../../hooks/useBlockWhileBotRespo
import { isIOSMobile } from '../../../utils';
import { useChatContext } from '../context/ChatProvider';

// TODO: Remove UIKit
export const ChatInput = () => {
const { channel, botUser, dataSource, handlers } = useChatContext();

Expand Down
33 changes: 28 additions & 5 deletions src/components/messages/OutgoingFileMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { css } from '@linaria/core';
import { styled } from '@linaria/react';
import { FileMessage } from '@sendbird/chat/message';
import { useState } from 'react';
Expand All @@ -9,7 +10,7 @@ import { Loader } from '../../foundation/components/Loader';
import { META_ARRAY_ASPECT_RATIO_KEY } from '../../utils/getImageAspectRatio';
import { formatCreatedAtToAMPM } from '../../utils/messageTimestamp';
import { BodyComponent, BodyContainer, DefaultSentTime } from '../MessageComponent';
import { css } from '@linaria/core';
import { FileViewer } from '../ui/FileViewer';

type Props = {
message: FileMessage;
Expand Down Expand Up @@ -87,11 +88,22 @@ const timestampContainer = css`
`;

const ImagePreview = ({ message }: Props) => {
const [viewer, setViewer] = useState(false);
const [fileUrl] = useState(() =>
message.messageParams?.file instanceof File ? URL.createObjectURL(message.messageParams?.file) : message.url,
);
const aspectRatio = message.metaArrays.find((it) => it.key === META_ARRAY_ASPECT_RATIO_KEY)?.value?.[0];
return <ImageWithPlaceholder src={fileUrl} alt={'file preview'} aspectRatio={aspectRatio ?? '1'} />;
return (
<>
<ImageWithPlaceholder
src={fileUrl}
alt={'file preview'}
aspectRatio={aspectRatio ?? '1'}
onClick={() => setViewer(true)}
/>
{viewer && <FileViewer message={message} onClose={() => setViewer(false)} />}
</>
);
};

// TODO: Refactor
Expand Down Expand Up @@ -125,6 +137,7 @@ const ImageContainer = styled.div<{ ratio: string }>`
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
.sendbird-theme--light & {
background-color: var(--sendbird-dark-background-100);
}
Expand All @@ -144,12 +157,22 @@ const StyledImage = styled.img<{ loaded: boolean }>`
transition: opacity 0.5s ease;
`;

const ImageWithPlaceholder = ({ src, alt, aspectRatio }: { src: string; alt: string; aspectRatio: string }) => {
const ImageWithPlaceholder = ({
src,
alt,
aspectRatio,
onClick,
}: {
src: string;
alt: string;
aspectRatio: string;
onClick?: () => void;
}) => {
const [loaded, setLoaded] = useState(false);

return (
<ImageContainer ratio={aspectRatio}>
{loaded && (
<ImageContainer ratio={aspectRatio} onClick={onClick}>
{!loaded && (
<Loader size={26}>
<Icon type={'spinner'} color={'onbackground3'} size={26} />
</Loader>
Expand Down
21 changes: 21 additions & 0 deletions src/components/ui/FileViewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { FileMessage } from '@sendbird/chat/message';

import { FileViewerView } from '@uikit/modules/GroupChannel/components/FileViewer/FileViewerView';

import { useChatContext } from '../chat/context/ChatProvider';

interface Props {
message: FileMessage;
onClose: () => void;
}
// TODO: Remove UIKit
export const FileViewer = ({ message, onClose }: Props) => {
const { dataSource } = useChatContext();
return (
<FileViewerView
message={message}
deleteMessage={(message: any) => dataSource.deleteMessage(message)}
onCancel={onClose}
/>
);
};

0 comments on commit 4e7d98e

Please sign in to comment.