Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { act, render, screen } from '@testing-library/react';
import { act, render, screen, waitFor } from '@testing-library/react';
import { fromPartial } from '@total-typescript/shoehorn';
import { WaveProgressBar } from '../../AudioPlayback';
import { ResizeObserverMock } from '../../../mock-builders/browser';
Expand Down Expand Up @@ -95,7 +95,9 @@ describe('WaveProgressBar', () => {
'2px',
),
).toBeTruthy();
expect(screen.getAllByTestId(AMPLITUDE_BAR_TEST_ID)).toHaveLength(7);
await waitFor(() => {
expect(screen.getAllByTestId(AMPLITUDE_BAR_TEST_ID)).toHaveLength(7);
});
});

it('does not recalculate the number of bars on root resize if ResizeObserver is unsupported', () => {
Expand Down
6 changes: 2 additions & 4 deletions src/components/AudioPlayback/AudioPlayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ export class AudioPlayer {

stop = () => {
this.pause();
this.state.partialNext({ isPlaying: false });
this.setSecondsElapsed(0);
if (this.elementRef) this.elementRef.currentTime = 0;
};
Expand Down Expand Up @@ -628,10 +629,7 @@ export class AudioPlayer {
if (audioElement) {
this.updateDurationFromElement(audioElement);
}
this.state.partialNext({
isPlaying: false,
secondsElapsed: audioElement?.duration ?? this.durationSeconds ?? 0,
});
this.stop();
};

const handleError = (e: HTMLMediaElementEventMap['error']) => {
Expand Down
18 changes: 18 additions & 0 deletions src/components/AudioPlayback/__tests__/AudioPlayer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,24 @@ describe('AudioPlayer', () => {
expect(player.elementRef.currentTime).toBe(0);
});

it('ended event resets playback state to initial position', () => {
const player = makePlayer();

player.play();
player.state.partialNext({ isPlaying: true });
player.setSecondsElapsed(50);

expect(player.state.getLatestValue().secondsElapsed).toBe(50);

player.elementRef.dispatchEvent(new Event('ended'));

const st = player.state.getLatestValue();
expect(st.isPlaying).toBe(false);
expect(st.secondsElapsed).toBe(0);
expect(st.progressPercent).toBe(0);
expect(player.elementRef.currentTime).toBe(0);
});

it('togglePlay delegates to play() / pause()', async () => {
const p = makePlayer();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ describe('WithAudioPlayback + useAudioPlayer', () => {
expect(st.progressPercent).toBeCloseTo(25, 5);
});

it('subscriptions: sets isPlaying=false and secondsElapsed to duration on Event "ended"', () => {
it('subscriptions: resets playback state on Event "ended"', () => {
let player;
renderWithProvider({
allowConcurrentPlayback,
Expand Down Expand Up @@ -216,7 +216,8 @@ describe('WithAudioPlayback + useAudioPlayer', () => {

const st = player.state.getLatestValue();
expect(st.isPlaying).toBe(false);
expect(st.secondsElapsed).toBe(200);
expect(st.secondsElapsed).toBe(0);
expect(st.progressPercent).toBe(0);
});

it('subscriptions: error with MediaError.code=4 logs and sets canPlayRecord=false', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ import { AudioRecorder } from '../AudioRecorder';
import { MediaRecordingState } from '../../classes';
import { WithAudioPlayback } from '../../../AudioPlayback';
import { ChatViewContext } from '../../../ChatView/ChatView';
import type {
AppSettingsAPIResponse,
SendFileAPIResponse,
} from '../../../../../../stream-chat-js/src';

const chatViewContextValue = {
activeChatView: 'channels',
Expand Down Expand Up @@ -376,6 +380,38 @@ describe('MessageInput', () => {
});
expect(sendMessageSpy).not.toHaveBeenCalled();
});

it('renders voice preview slot after stopping recording when multiple async messages are enabled', async () => {
MediaRecorderMock.autoEmitDataOnStop = true;
const {
channels: [channel],
client,
} = await initClientWithChannels({
channelsData: [{ channel: { own_capabilities: ['upload-file'] } }],
});

vi.spyOn(client, 'getAppSettings').mockResolvedValue({} as AppSettingsAPIResponse);
vi.spyOn(channel, 'sendFile').mockResolvedValue({
file: fileObjectURL,
} as SendFileAPIResponse);

await renderComponent({
channelStateCtx: { channel },
chatCtx: { client },
props: { asyncMessagesMultiSendEnabled: true },
});

fireEvent.click(screen.getByTestId(START_RECORDING_AUDIO_BUTTON_TEST_ID));
await waitFor(() => {
expect(screen.getByTestId(AUDIO_RECORDER_TEST_ID)).toBeInTheDocument();
});

fireEvent.click(screen.getByTestId(AUDIO_RECORDER_STOP_BTN_TEST_ID));

await waitFor(() => {
expect(screen.getByTestId('voice-preview-slot')).toBeInTheDocument();
});
});
});

const recorderMock = {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
.str-chat__audio-recorder__recording-playback,
.str-chat__audio-recorder__recording-preview {
flex: 1;
min-width: 0;
display: flex;
align-items: center;
gap: var(--spacing-md);
Expand Down Expand Up @@ -101,13 +102,12 @@

.str-chat__wave-progress-bar__track-container,
.str-chat__waveform-box-container {
//flex: 1;
flex: 1 1 auto;
display: flex;
align-items: center;
width: 100%;
width: auto;
min-width: 0;
//overflow-x: hidden;
flex-shrink: 1;
}

.str-chat__wave-progress-bar__track-container {
Expand All @@ -120,7 +120,7 @@
.str-chat__wave-progress-bar__track {
display: flex;
min-width: 0;
width: unset;
width: 100%;
align-items: center;
flex-wrap: nowrap;
height: 2rem;
Expand All @@ -139,8 +139,7 @@
padding-inline: var(--spacing-xs);

.str-chat__wave-progress-bar__track {
flex: unset;
//width: max-content;
flex: 1 1 auto;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/MessageComposer/MessageComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const MessageComposerProvider = (props: PropsWithChildren<MessageComposerProps>)

useEffect(
() => () => {
messageComposer.createDraft();
messageComposer.createDraft().finally(() => messageComposer.clear());
},
[messageComposer],
);
Expand Down
7 changes: 0 additions & 7 deletions src/components/TextareaComposer/TextareaComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -267,13 +267,6 @@ export const TextareaComposer = ({
textareaRef.current.focus();
}, [attachments, focus, quotedMessage, textareaRef]);

useEffect(
() => () => {
messageComposer.clear();
},
[messageComposer],
);

useLayoutEffect(() => {
/**
* It is important to perform set text and after that the range
Expand Down
6 changes: 1 addition & 5 deletions src/context/ChannelListContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,10 @@ export const ChannelListContextProvider = ({
</ChannelListContext.Provider>
);

export const useChannelListContext = (componentName?: string) => {
export const useChannelListContext = () => {
const contextValue = useContext(ChannelListContext);

if (!contextValue) {
console.warn(
`The useChannelListContext hook was called outside of the ChannelListContext provider. Make sure this hook is called within the ChannelList component. The errored call is located in the ${componentName} component.`,
);

return {} as ChannelListContextValue;
}

Expand Down
Loading