Skip to content

Commit 44902e7

Browse files
authored
feat: add missing configuration parameters for AttachmentManager and TextComposer (#1520)
1 parent 4015112 commit 44902e7

File tree

7 files changed

+93
-8
lines changed

7 files changed

+93
-8
lines changed

src/messageComposer/attachmentManager.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ export class AttachmentManager {
8989
return this.composer.config.attachments;
9090
}
9191

92+
get acceptedFiles() {
93+
return this.config.acceptedFiles;
94+
}
95+
96+
set acceptedFiles(acceptedFiles: AttachmentManagerConfig['acceptedFiles']) {
97+
this.composer.updateConfig({ attachments: { acceptedFiles } });
98+
}
99+
92100
get fileUploadFilter() {
93101
return this.config.fileUploadFilter;
94102
}

src/messageComposer/configuration/configuration.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ export const DEFAULT_LINK_PREVIEW_MANAGER_CONFIG: LinkPreviewsManagerConfig = {
2626
};
2727

2828
export const DEFAULT_ATTACHMENT_MANAGER_CONFIG: AttachmentManagerConfig = {
29+
acceptedFiles: [], // an empty array means all files are accepted
2930
fileUploadFilter: () => true,
3031
maxNumberOfFilesPerMessage: API_MAX_FILES_ALLOWED_PER_MESSAGE,
3132
};
3233

3334
export const DEFAULT_TEXT_COMPOSER_CONFIG: TextComposerConfig = {
35+
enabled: true,
3436
publishTypingEvents: true,
3537
};
3638

src/messageComposer/configuration/types.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ export type DraftsConfiguration = {
1212
enabled: boolean;
1313
};
1414
export type TextComposerConfig = {
15-
/** If true, triggers typing events on text input keystroke */
15+
/** If false, the text input, change and selection events are disabled */
16+
enabled: boolean;
17+
/** If true, triggers typing events on text input keystroke. Disabled for threads and message editing by default. */
1618
publishTypingEvents: boolean;
1719
/** Default value for the message input */
1820
defaultValue?: string;
@@ -30,6 +32,11 @@ export type AttachmentManagerConfig = {
3032
fileUploadFilter: FileUploadFilter;
3133
/** Maximum number of attachments allowed per message */
3234
maxNumberOfFilesPerMessage: number;
35+
/**
36+
* Array of one or more file types, or unique file type specifiers (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/accept#unique_file_type_specifiers),
37+
* describing which file types to allow to select when uploading files.
38+
*/
39+
acceptedFiles: string[];
3340
// todo: refactor this. We want a pipeline where it would be possible to customize the preparation, upload, and post-upload steps.
3441
/** Function that allows to customize the upload request. */
3542
doUploadRequest?: UploadRequestFn;

src/messageComposer/messageComposer.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ export class MessageComposer {
236236
return this.compositionContext.legacyThreadId;
237237
}
238238

239-
// check if message is a reply, get parentMessageId
239+
// check if the message is a reply, get parentMessageId
240240
if (typeof this.compositionContext.parent_id === 'string') {
241241
return this.compositionContext.parent_id;
242242
}
@@ -333,10 +333,6 @@ export class MessageComposer {
333333
initEditingAuditState = (
334334
composition?: DraftResponse | MessageResponse | LocalMessage,
335335
) => initEditingAuditState(composition);
336-
// this.config?.drafts.enabled || !compositionIsDraftResponse(composition)
337-
// ? composition
338-
// : undefined,
339-
// );
340336

341337
private logStateUpdateTimestamp() {
342338
this.editingAuditState.partialNext({

src/messageComposer/textComposer.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ export class TextComposer {
6868
return this.composer.config.text;
6969
}
7070

71+
get enabled() {
72+
return this.composer.config.text.enabled;
73+
}
74+
75+
set enabled(enabled: boolean) {
76+
this.composer.updateConfig({ text: { enabled } });
77+
}
78+
7179
set defaultValue(defaultValue: string) {
7280
this.composer.updateConfig({ text: { defaultValue } });
7381
}
@@ -138,10 +146,13 @@ export class TextComposer {
138146
};
139147

140148
setText = (text: string) => {
149+
if (!this.enabled) return;
141150
this.state.partialNext({ text });
142151
};
143152

144153
insertText = ({ text, selection }: { text: string; selection?: TextSelection }) => {
154+
if (!this.enabled) return;
155+
145156
const finalSelection: TextSelection = selection ?? {
146157
start: this.text.length,
147158
end: this.text.length,
@@ -189,6 +200,7 @@ export class TextComposer {
189200
selection: TextSelection;
190201
text: string;
191202
}) => {
203+
if (!this.enabled) return;
192204
const output = await this.middlewareExecutor.execute('onChange', {
193205
state: {
194206
...this.state.getLatestValue(),
@@ -209,6 +221,7 @@ export class TextComposer {
209221

210222
// todo: document how to register own middleware handler to simulate onSelectUser prop
211223
handleSelect = async (target: TextComposerSuggestion<unknown>) => {
224+
if (!this.enabled) return;
212225
const output = await this.middlewareExecutor.execute(
213226
'onSuggestionItemSelect',
214227
{

test/unit/MessageComposer/attachmentManager.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ describe('AttachmentManager', () => {
176176

177177
describe('getters', () => {
178178
it('should retrieve attachments config from composer', () => {
179-
const config: AttachmentManagerConfig = {
179+
const config: Partial<AttachmentManagerConfig> = {
180180
doUploadRequest: () => {
181181
return Promise.resolve({ file: 'x' });
182182
},
@@ -186,7 +186,7 @@ describe('AttachmentManager', () => {
186186
const {
187187
messageComposer: { attachmentManager },
188188
} = setup({ config });
189-
expect(attachmentManager.config).toEqual(config);
189+
expect(attachmentManager.config).toEqual({ ...config, acceptedFiles: [] });
190190
});
191191

192192
it('should return the correct values from state', async () => {

test/unit/MessageComposer/textComposer.test.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,15 @@ describe('TextComposer', () => {
199199
textComposer.state.partialNext({ text: '' });
200200
expect(textComposer.textIsEmpty).toBe(true);
201201
});
202+
203+
it('gets the current value of enabled', () => {
204+
const {
205+
messageComposer: { textComposer },
206+
} = setup();
207+
expect(textComposer.enabled).toBe(true);
208+
textComposer.enabled = false;
209+
expect(textComposer.enabled).toBe(false);
210+
});
202211
});
203212

204213
describe('initState', () => {
@@ -372,6 +381,18 @@ describe('TextComposer', () => {
372381
textComposer.setText('New text');
373382
expect(textComposer.text).toBe('New text');
374383
});
384+
it('should not update the text when disabled', () => {
385+
const message: LocalMessage = {
386+
id: 'test-message',
387+
type: 'regular',
388+
text: 'Hello world',
389+
};
390+
const {
391+
messageComposer: { textComposer },
392+
} = setup({ composition: message, config: { enabled: false } });
393+
textComposer.setText('New text');
394+
expect(textComposer.text).toBe(message.text);
395+
});
375396
});
376397

377398
describe('insertText', () => {
@@ -460,6 +481,14 @@ describe('TextComposer', () => {
460481
textComposer.insertText({ text: insertedText, selection: { start: 7, end: 9 } });
461482
expect(textComposer.text).toBe('Hello wHi ');
462483
});
484+
485+
it('should not insert text if disabled', () => {
486+
const {
487+
messageComposer: { textComposer },
488+
} = setup({ composition: message, config: { enabled: false } });
489+
textComposer.insertText({ text: ' beautiful', selection: { start: 5, end: 5 } });
490+
expect(textComposer.text).toBe(message.text);
491+
});
463492
});
464493

465494
describe('closeSuggestions', () => {
@@ -512,6 +541,22 @@ describe('TextComposer', () => {
512541
);
513542
});
514543

544+
it('should not update state with middleware result if disabled', async () => {
545+
const {
546+
messageComposer: { textComposer },
547+
} = setup({ config: { enabled: false } });
548+
textComposer.state.next(initialState);
549+
const initialText = textComposer.text;
550+
const initialSelection = textComposer.selection;
551+
await textComposer.handleChange({
552+
text: 'Test message',
553+
selection: { start: 12, end: 12 },
554+
});
555+
556+
expect(textComposer.text).toBe(initialText);
557+
expect(textComposer.selection).toEqual(initialSelection);
558+
});
559+
515560
it('should not update state if middleware returns discard status', async () => {
516561
const {
517562
messageComposer: { textComposer },
@@ -631,6 +676,20 @@ describe('TextComposer', () => {
631676
);
632677
});
633678

679+
it('should not update state with middleware result if disabled', async () => {
680+
const {
681+
messageComposer: { textComposer },
682+
} = setup({ config: { enabled: false } });
683+
textComposer.state.next(initialState);
684+
685+
const target = { id: 'user-1' };
686+
const executeSpy = vi.spyOn(textComposer.middlewareExecutor, 'execute');
687+
executeSpy.mockResolvedValueOnce(textComposerMiddlewareExecuteOutput);
688+
await textComposer.handleSelect(target);
689+
690+
expect(textComposer.state.getLatestValue()).toEqual(initialState);
691+
});
692+
634693
it('should not update state if middleware returns discard status', async () => {
635694
const {
636695
messageComposer: { textComposer },

0 commit comments

Comments
 (0)