Skip to content

Commit f09bf36

Browse files
authored
[Chat] File Sharing Refactor (#4464)
1 parent d4ca592 commit f09bf36

42 files changed

Lines changed: 484 additions & 343 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "minor",
3+
"area": "improvement",
4+
"workstream": "File Sharing Refactor",
5+
"comment": "Updated File Sharing Public APIs",
6+
"packageName": "@azure/communication-react",
7+
"email": "109105353+jpeng-ms@users.noreply.github.com",
8+
"dependentChangeType": "patch"
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "minor",
3+
"area": "improvement",
4+
"workstream": "File Sharing Refactor",
5+
"comment": "Updated File Sharing Public APIs",
6+
"packageName": "@azure/communication-react",
7+
"email": "109105353+jpeng-ms@users.noreply.github.com",
8+
"dependentChangeType": "patch"
9+
}

packages/communication-react/review/beta/communication-react.api.md

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,15 @@ export interface AttachmentMetadata {
166166
extension?: string;
167167
id: string;
168168
name: string;
169-
progress?: number;
170-
uploadError?: AttachmentUploadStatus;
171169
url?: string;
172170
}
173171

172+
// @beta
173+
export interface AttachmentMetadataWithProgress extends AttachmentMetadata {
174+
error?: AttachmentProgressError;
175+
progress?: number;
176+
}
177+
174178
// @beta
175179
export interface AttachmentOptions {
176180
// (undocumented)
@@ -179,16 +183,28 @@ export interface AttachmentOptions {
179183
uploadOptions?: AttachmentUploadOptions;
180184
}
181185

182-
// @beta (undocumented)
183-
export interface AttachmentUploadAdapter {
186+
// @beta
187+
export interface AttachmentProgressError {
188+
// (undocumented)
189+
message: string;
190+
}
191+
192+
// @beta
193+
export type AttachmentRemovalHandler = (attachmentId: string) => void;
194+
195+
// @beta
196+
export type AttachmentSelectionHandler = (attachmentUploads: AttachmentUploadTask[]) => void;
197+
198+
// @internal (undocumented)
199+
export interface _AttachmentUploadAdapter {
184200
// (undocumented)
185201
cancelUpload: (id: string) => void;
186202
// (undocumented)
187203
clearUploads: () => void;
188204
// (undocumented)
189-
registerActiveUploads: (files: File[]) => AttachmentUploadManager[];
205+
registerActiveUploads: (files: File[]) => AttachmentUploadTask[];
190206
// (undocumented)
191-
registerCompletedUploads: (metadata: AttachmentMetadata[]) => AttachmentUploadManager[];
207+
registerCompletedUploads: (metadata: AttachmentMetadata[]) => AttachmentUploadTask[];
192208
// (undocumented)
193209
updateUploadMetadata: (id: string, metadata: AttachmentMetadata) => void;
194210
// (undocumented)
@@ -197,35 +213,25 @@ export interface AttachmentUploadAdapter {
197213
updateUploadStatusMessage: (id: string, errorMessage: string) => void;
198214
}
199215

200-
// @beta
201-
export type AttachmentUploadHandler = (attachmentUploads: AttachmentUploadManager[]) => void;
202-
203-
// @beta
204-
export interface AttachmentUploadManager {
205-
file?: File;
206-
id: string;
207-
notifyCompleted: (metadata: AttachmentMetadata) => void;
208-
notifyFailed: (message: string) => void;
209-
notifyProgressChanged: (value: number) => void;
210-
}
211-
212216
// @beta (undocumented)
213217
export interface AttachmentUploadOptions {
214218
disableMultipleUploads?: boolean;
215-
handler: AttachmentUploadHandler;
219+
handleAttachmentRemoval?: AttachmentRemovalHandler;
220+
handleAttachmentSelection: AttachmentSelectionHandler;
216221
supportedMediaTypes?: string[];
217222
}
218223

219-
// @beta
220-
export interface AttachmentUploadStatus {
221-
// (undocumented)
222-
message: string;
223-
// (undocumented)
224-
timestamp: number;
225-
}
224+
// @internal
225+
export type _AttachmentUploadsUiState = Record<string, AttachmentMetadataWithProgress>;
226226

227227
// @beta
228-
export type AttachmentUploadsUiState = Record<string, AttachmentMetadata>;
228+
export interface AttachmentUploadTask {
229+
file?: File;
230+
notifyUploadCompleted: (id: string, url: string) => void;
231+
notifyUploadFailed: (message: string) => void;
232+
notifyUploadProgressChanged: (value: number) => void;
233+
taskId: string;
234+
}
229235

230236
// @public
231237
export type AvatarPersonaData = {
@@ -1078,9 +1084,9 @@ export interface CallWithChatAdapterManagement {
10781084
addParticipant(participant: CommunicationUserIdentifier): Promise<void>;
10791085
allowUnsupportedBrowserVersion(): void;
10801086
askDevicePermission(constrain: PermissionConstraints): Promise<void>;
1081-
// @beta (undocumented)
1087+
// @internal (undocumented)
10821088
cancelUpload: (id: string) => void;
1083-
// @beta (undocumented)
1089+
// @internal (undocumented)
10841090
clearUploads: () => void;
10851091
createStreamView(remoteUserId?: string, options?: VideoStreamOptions): Promise<void | CreateVideoStreamViewResult>;
10861092
deleteMessage(messageId: string): Promise<void>;
@@ -1105,10 +1111,10 @@ export interface CallWithChatAdapterManagement {
11051111
queryMicrophones(): Promise<AudioDeviceInfo[]>;
11061112
querySpeakers(): Promise<AudioDeviceInfo[]>;
11071113
raiseHand(): Promise<void>;
1108-
// @beta (undocumented)
1109-
registerActiveUploads: (files: File[]) => AttachmentUploadManager[];
1110-
// @beta (undocumented)
1111-
registerCompletedUploads: (metadata: AttachmentMetadata[]) => AttachmentUploadManager[];
1114+
// @internal (undocumented)
1115+
registerActiveUploads: (files: File[]) => AttachmentUploadTask[];
1116+
// @internal (undocumented)
1117+
registerCompletedUploads: (metadata: AttachmentMetadata[]) => AttachmentUploadTask[];
11121118
removeParticipant(userId: string): Promise<void>;
11131119
// @beta
11141120
removeParticipant(participant: CommunicationIdentifier): Promise<void>;
@@ -1118,6 +1124,8 @@ export interface CallWithChatAdapterManagement {
11181124
resumeCall: () => Promise<void>;
11191125
sendDtmfTone: (dtmfTone: DtmfTone_2) => Promise<void>;
11201126
sendMessage(content: string, options?: SendMessageOptions): Promise<void>;
1127+
// @beta
1128+
sendMessageWithAttachments(content: string, attachments: AttachmentMetadata[]): Promise<void>;
11211129
sendReadReceipt(chatMessageId: string): Promise<void>;
11221130
sendTypingIndicator(): Promise<void>;
11231131
setCamera(sourceInfo: VideoDeviceInfo, options?: VideoStreamOptions): Promise<void>;
@@ -1143,11 +1151,11 @@ export interface CallWithChatAdapterManagement {
11431151
updateBackgroundPickerImages(backgroundImages: VideoBackgroundImage[]): void;
11441152
updateMessage(messageId: string, content: string, metadata?: Record<string, string>): Promise<void>;
11451153
updateSelectedVideoBackgroundEffect(selectedVideoBackground: VideoBackgroundEffect): void;
1146-
// @beta (undocumented)
1154+
// @internal (undocumented)
11471155
updateUploadMetadata: (id: string, metadata: AttachmentMetadata) => void;
1148-
// @beta (undocumented)
1156+
// @internal (undocumented)
11491157
updateUploadProgress: (id: string, progress: number) => void;
1150-
// @beta (undocumented)
1158+
// @internal (undocumented)
11511159
updateUploadStatusMessage: (id: string, errorMessage: string) => void;
11521160
}
11531161

@@ -1261,8 +1269,8 @@ export interface CallWithChatAdapterSubscriptions {
12611269

12621270
// @public
12631271
export interface CallWithChatAdapterUiState {
1264-
// @beta
1265-
attachmentUploads?: AttachmentUploadsUiState;
1272+
// @internal
1273+
_attachmentUploads?: _AttachmentUploadsUiState;
12661274
isLocalPreviewMicrophoneEnabled: boolean;
12671275
page: CallCompositePage;
12681276
// @beta
@@ -1677,7 +1685,7 @@ export type CaptionsReceivedListener = (event: {
16771685
}) => void;
16781686

16791687
// @public
1680-
export type ChatAdapter = ChatAdapterThreadManagement & AdapterState<ChatAdapterState> & Disposable_2 & ChatAdapterSubscribers & AttachmentUploadAdapter;
1688+
export type ChatAdapter = ChatAdapterThreadManagement & AdapterState<ChatAdapterState> & Disposable_2 & ChatAdapterSubscribers & _AttachmentUploadAdapter;
16811689

16821690
// @public
16831691
export type ChatAdapterState = ChatAdapterUiState & ChatCompositeClientState;
@@ -1713,6 +1721,7 @@ export interface ChatAdapterThreadManagement {
17131721
removeParticipant(userId: string): Promise<void>;
17141722
removeResourceFromCache(resourceDetails: ResourceDetails): void;
17151723
sendMessage(content: string, options?: SendMessageOptions): Promise<void>;
1724+
sendMessageWithAttachments(content: string, attachments: AttachmentMetadata[]): Promise<void>;
17161725
sendReadReceipt(chatMessageId: string): Promise<void>;
17171726
sendTypingIndicator(): Promise<void>;
17181727
setTopic(topicName: string): Promise<void>;
@@ -1724,7 +1733,7 @@ export interface ChatAdapterThreadManagement {
17241733
// @public
17251734
export type ChatAdapterUiState = {
17261735
error?: Error;
1727-
attachmentUploads?: AttachmentUploadsUiState;
1736+
_attachmentUploads?: _AttachmentUploadsUiState;
17281737
};
17291738

17301739
// @public
@@ -3882,7 +3891,7 @@ export const RichTextSendBox: (props: RichTextSendBoxProps) => JSX.Element;
38823891

38833892
// @beta
38843893
export interface RichTextSendBoxProps {
3885-
activeAttachmentUploads?: AttachmentMetadata[];
3894+
attachmentsWithProgress?: AttachmentMetadataWithProgress[];
38863895
autoFocus?: 'sendBoxTextField';
38873896
disabled?: boolean;
38883897
onCancelAttachmentUpload?: (attachmentId: string) => void;
@@ -3954,7 +3963,7 @@ export interface SendBoxErrorBarError {
39543963
// @public
39553964
export interface SendBoxProps {
39563965
// @beta
3957-
activeAttachmentUploads?: AttachmentMetadata[];
3966+
attachmentsWithProgress?: AttachmentMetadataWithProgress[];
39583967
autoFocus?: 'sendBoxTextField';
39593968
disabled?: boolean;
39603969
// @beta

packages/communication-react/src/index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -324,10 +324,12 @@ export type { AttachmentMetadata, AttachmentOptions } from '../../react-componen
324324
export type { SendBoxErrorBarError } from '../../react-components/src';
325325
/* @conditional-compile-remove(attachment-upload) */
326326
export type {
327-
AttachmentUploadStatus,
328-
AttachmentUploadHandler,
327+
AttachmentProgressError,
328+
AttachmentSelectionHandler,
329+
AttachmentRemovalHandler,
329330
AttachmentUploadOptions,
330-
AttachmentUploadManager
331+
AttachmentUploadTask,
332+
AttachmentMetadataWithProgress
331333
} from '../../react-components/src';
332334

333335
/* @conditional-compile-remove(attachment-download) */

packages/react-components/src/components/AttachmentCard.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { Announcer } from './Announcer';
2626
import { useEffect, useState, useMemo } from 'react';
2727
import { _AttachmentUploadCardsStrings } from './AttachmentUploadCards';
2828
import { useLocaleAttachmentCardStringsTrampoline } from './utils/common';
29-
import { AttachmentMetadata, AttachmentMenuAction } from '../types/Attachment';
29+
import { AttachmentMetadata, AttachmentMenuAction, AttachmentMetadataWithProgress } from '../types/Attachment';
3030
import { useAttachmentCardStyles, attachmentNameContainerClassName } from './styles/AttachmentCard.styles';
3131

3232
/**
@@ -37,7 +37,7 @@ export interface _AttachmentCardProps {
3737
/**
3838
* Attachment details including name, extension, url, etc.
3939
*/
40-
attachment: AttachmentMetadata;
40+
attachment: AttachmentMetadata | AttachmentMetadataWithProgress;
4141
/**
4242
* An array of menu actions to be displayed in the attachment card.
4343
*/
@@ -61,9 +61,11 @@ export interface _AttachmentCardProps {
6161
export const _AttachmentCard = (props: _AttachmentCardProps): JSX.Element => {
6262
const { attachment, menuActions, onActionHandlerFailed } = props;
6363
const attachmentCardStyles = useAttachmentCardStyles();
64+
6465
const progress = useMemo(() => {
65-
return attachment.progress;
66-
}, [attachment.progress]);
66+
return 'progress' in attachment ? attachment.progress : undefined;
67+
}, [attachment]);
68+
6769
const isUploadComplete = useMemo(() => {
6870
return progress !== undefined && progress > 0 && progress < 1;
6971
}, [progress]);

packages/react-components/src/components/AttachmentUploadCards.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ describe('AttachmentUploadCards should be rendered properly', () => {
1818

1919
it('should render the component', async () => {
2020
const props = {
21-
activeAttachmentUploads: [
21+
attachmentsWithProgress: [
2222
{
2323
id: 'MockId',
2424
name: 'MockAttachmentUpload',
@@ -30,9 +30,9 @@ describe('AttachmentUploadCards should be rendered properly', () => {
3030
expect(await screen.findByText('MockAttachmentUpload')).toBeDefined();
3131
});
3232

33-
it('should not render the component with no activeAttachmentUploads', async () => {
33+
it('should not render the component with no attachmentsWithProgress', async () => {
3434
const props = {
35-
activeAttachmentUploads: undefined
35+
attachmentsWithProgress: undefined
3636
} as AttachmentUploadCardsProps;
3737
renderAttachmentUploadCardWithDefaults(props);
3838
expect(screen.queryByText('MockAttachmentUpload')).toBeNull();
@@ -41,7 +41,7 @@ describe('AttachmentUploadCards should be rendered properly', () => {
4141

4242
const renderAttachmentUploadCardWithDefaults = (props?: Partial<AttachmentUploadCardsProps>): void => {
4343
const mergedProps: AttachmentUploadCardsProps = {
44-
activeAttachmentUploads: props?.activeAttachmentUploads ?? [],
44+
attachmentsWithProgress: props?.attachmentsWithProgress ?? [],
4545
...(props ?? {})
4646
};
4747

packages/react-components/src/components/AttachmentUploadCards.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Icon, mergeStyles } from '@fluentui/react';
55
import React, { useMemo } from 'react';
66
import { _AttachmentCard } from './AttachmentCard';
77
import { _AttachmentCardGroup } from './AttachmentCardGroup';
8-
import { AttachmentMetadata } from '../types/Attachment';
8+
import { AttachmentMetadataWithProgress } from '../types/Attachment';
99
import { useLocaleAttachmentCardStringsTrampoline } from './utils/common';
1010

1111
/**
@@ -29,10 +29,9 @@ export interface _AttachmentUploadCardsStrings {
2929
*/
3030
export interface AttachmentUploadCardsProps {
3131
/**
32-
* Optional array of active attachment uploads where each object has attibutes
33-
* of a attachment upload like name, progress, errormessage etc.
32+
* Optional array of {@link AttachmentMetadataWithProgress}
3433
*/
35-
activeAttachmentUploads?: AttachmentMetadata[];
34+
attachmentsWithProgress?: AttachmentMetadataWithProgress[];
3635
/**
3736
* Optional callback to remove the attachment upload before sending by clicking on
3837
* cancel icon.
@@ -50,7 +49,7 @@ const actionIconStyle = { height: '1rem' };
5049
* @internal
5150
*/
5251
export const _AttachmentUploadCards = (props: AttachmentUploadCardsProps): JSX.Element => {
53-
const attachments = props.activeAttachmentUploads;
52+
const attachments = props.attachmentsWithProgress;
5453
const localeStrings = useLocaleAttachmentCardStringsTrampoline();
5554
const removeAttachmentButtonString = useMemo(
5655
() => () => {
@@ -67,7 +66,7 @@ export const _AttachmentUploadCards = (props: AttachmentUploadCardsProps): JSX.E
6766
<_AttachmentCardGroup>
6867
{attachments &&
6968
attachments
70-
.filter((attachment) => !attachment.uploadError)
69+
.filter((attachment) => !attachment.error)
7170
.map((attachment) => (
7271
<_AttachmentCard
7372
attachment={attachment}

packages/react-components/src/components/ChatMessage/MyMessageComponents/ChatMessageComponentAsEditBox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ export const ChatMessageComponentAsEditBox = (props: ChatMessageComponentAsEditB
119119
attachmentMetadata.length > 0 && (
120120
<div style={{ margin: '0.25rem' }}>
121121
<_AttachmentUploadCards
122-
activeAttachmentUploads={attachmentMetadata}
122+
attachmentsWithProgress={attachmentMetadata}
123123
onCancelAttachmentUpload={(attachmentId) => {
124124
setAttachmentMetadata(attachmentMetadata?.filter((attachment) => attachment.id !== attachmentId));
125125
}}

packages/react-components/src/components/ChatMessage/MyMessageComponents/ChatMessageComponentAsRichTextEditBox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ export const ChatMessageComponentAsRichTextEditBox = (
169169
<Stack className={attachmentUploadCardsStyles}>
170170
<FluentV9ThemeProvider v8Theme={theme}>
171171
<_AttachmentUploadCards
172-
activeAttachmentUploads={attachmentMetadata}
172+
attachmentsWithProgress={attachmentMetadata}
173173
onCancelAttachmentUpload={onCancelAttachmentUpload}
174174
/>
175175
</FluentV9ThemeProvider>

0 commit comments

Comments
 (0)