Skip to content

Commit 5f15088

Browse files
committed
fix: delayed modal closure on exiting animations
1 parent 8b55d62 commit 5f15088

File tree

3 files changed

+35
-12
lines changed

3 files changed

+35
-12
lines changed

package/src/components/Poll/CreatePollContent.tsx

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,8 @@ export const CreatePollContent = () => {
107107
}, [currentOptionPositions, normalizedCreatePollOptionGap, optionIdsKey]);
108108

109109
const onBackPressHandler = useCallback(() => {
110-
pollComposer.initState();
111110
closePollCreationDialog?.();
112-
}, [pollComposer, closePollCreationDialog]);
111+
}, [closePollCreationDialog]);
113112

114113
const onCreatePollPressHandler = useCallback(async () => {
115114
await createAndSendPoll();
@@ -220,27 +219,49 @@ export const CreatePoll = ({
220219
> &
221220
Pick<InputMessageInputContextValue, 'CreatePollContent'>) => {
222221
const messageComposer = useMessageComposer();
222+
const [isClosing, setIsClosing] = useState(false);
223+
const closeFrameRef = useRef<number | null>(null);
224+
225+
const closeCreatePollDialog = useCallback(() => {
226+
if (closeFrameRef.current !== null) {
227+
return;
228+
}
229+
230+
setIsClosing(true);
231+
// Let the modal render once with exit animations disabled before we dismiss it.
232+
closeFrameRef.current = requestAnimationFrame(() => {
233+
closeFrameRef.current = null;
234+
closePollCreationDialog?.();
235+
});
236+
}, [closePollCreationDialog]);
237+
238+
useEffect(() => {
239+
return () => {
240+
if (closeFrameRef.current !== null) {
241+
cancelAnimationFrame(closeFrameRef.current);
242+
}
243+
// Reset after teardown so poll field exit animations do not delay modal dismissal.
244+
messageComposer.pollComposer.initState();
245+
};
246+
}, [messageComposer]);
223247

224248
const createAndSendPoll = useCallback(async () => {
225249
try {
226250
await messageComposer.createPoll();
227251
await sendMessage();
228-
closePollCreationDialog?.();
229-
// it's important that the reset of the pollComposer state happens
230-
// after we've already closed the modal; as otherwise we'd get weird
231-
// UI behaviour.
232-
messageComposer.pollComposer.initState();
252+
closeCreatePollDialog();
233253
} catch (error) {
234254
console.log('Error creating a poll and sending a message:', error);
235255
}
236-
}, [messageComposer, sendMessage, closePollCreationDialog]);
256+
}, [closeCreatePollDialog, messageComposer, sendMessage]);
237257

238258
return (
239259
<CreatePollContentProvider
240260
value={{
241-
closePollCreationDialog,
261+
closePollCreationDialog: closeCreatePollDialog,
242262
createAndSendPoll,
243263
createPollOptionGap,
264+
isClosing,
244265
sendMessage,
245266
}}
246267
>

package/src/components/Poll/components/MultipleVotesSettings.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Animated, { LinearTransition, StretchInY, StretchOutY } from 'react-nativ
55

66
import { PollComposerState } from 'stream-chat';
77

8-
import { useTheme, useTranslationContext } from '../../../contexts';
8+
import { useCreatePollContentContext, useTheme, useTranslationContext } from '../../../contexts';
99
import { useMessageComposer } from '../../../contexts/messageInputContext/hooks/useMessageComposer';
1010
import { useStableCallback } from '../../../hooks';
1111
import { useStateStore } from '../../../hooks/useStateStore';
@@ -91,6 +91,7 @@ const MaxVotesTextInput = () => {
9191
export const MultipleVotesSettings = () => {
9292
const [allowMaxVotesPerPerson, setAllowMaxVotesPerPerson] = useState<boolean>(false);
9393
const { t } = useTranslationContext();
94+
const { isClosing } = useCreatePollContentContext();
9495
const messageComposer = useMessageComposer();
9596
const { pollComposer } = messageComposer;
9697
const { updateFields } = pollComposer;
@@ -133,7 +134,7 @@ export const MultipleVotesSettings = () => {
133134
<Animated.View
134135
layout={LinearTransition.duration(200)}
135136
entering={StretchInY.duration(200)}
136-
exiting={StretchOutY.duration(200)}
137+
exiting={isClosing ? undefined : StretchOutY.duration(200)}
137138
style={[styles.settingsWrapper, multipleAnswers.settingsWrapper]}
138139
>
139140
<View style={[styles.optionCard, multipleAnswers.optionCard]}>
@@ -152,7 +153,7 @@ export const MultipleVotesSettings = () => {
152153
{allowMaxVotesPerPerson ? (
153154
<Animated.View
154155
entering={StretchInY.duration(200)}
155-
exiting={StretchOutY.duration(200)}
156+
exiting={isClosing ? undefined : StretchOutY.duration(200)}
156157
style={[styles.row, multipleAnswers.row]}
157158
>
158159
<Button

package/src/contexts/pollContext/createPollContentContext.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export type CreatePollContentContextValue = {
99
createAndSendPoll: () => Promise<void>;
1010
sendMessage: MessageInputContextValue['sendMessage'];
1111
closePollCreationDialog?: () => void;
12+
isClosing?: boolean;
1213
/**
1314
* Vertical gap between poll options in the poll creation screen.
1415
*

0 commit comments

Comments
 (0)