Skip to content

Commit

Permalink
fix: await onClose for voice message input before displaying permissi…
Browse files Browse the repository at this point in the history
…on alert
  • Loading branch information
bang9 committed Nov 3, 2023
1 parent 6f4386d commit 62ef277
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { forwardRef, useState } from 'react';
import React, { forwardRef } from 'react';
import {
NativeSyntheticEvent,
Platform,
Expand All @@ -18,7 +18,7 @@ import {
useToast,
useUIKitTheme,
} from '@sendbird/uikit-react-native-foundation';
import { Logger, useIIFE } from '@sendbird/uikit-utils';
import { Logger, useDeferredModalState, useIIFE } from '@sendbird/uikit-utils';

import { VOICE_MESSAGE_META_ARRAY_DURATION_KEY, VOICE_MESSAGE_META_ARRAY_MESSAGE_TYPE_KEY } from '../../constants';
import { useChannelInputItems } from '../../hooks/useChannelInputItems';
Expand Down Expand Up @@ -60,7 +60,12 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
const { openSheet } = useBottomSheet();
const toast = useToast();

const [voiceMessageInputVisible, setVoiceMessageInputVisible] = useState(false);
const {
onClose,
onDismiss,
visible: voiceMessageInputVisible,
setVisible: setVoiceMessageInputVisible,
} = useDeferredModalState();

const messageReplyParams = useIIFE(() => {
const { groupChannel } = sbOptions.uikit;
Expand Down Expand Up @@ -187,15 +192,13 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
{voiceMessageEnabled && VoiceMessageInput && (
<Modal
disableBackgroundClose
onClose={() => setVoiceMessageInputVisible(false)}
onClose={onClose}
onDismiss={onDismiss}
backgroundStyle={{ justifyContent: 'flex-end' }}
visible={voiceMessageInputVisible}
type={'slide-no-gesture'}
>
<VoiceMessageInput
onClose={() => setVoiceMessageInputVisible(false)}
onSend={({ file, duration }) => sendVoiceMessage(file, duration)}
/>
<VoiceMessageInput onClose={onClose} onSend={({ file, duration }) => sendVoiceMessage(file, duration)} />
</Modal>
)}
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ import useVoiceMessageInput from '../../hooks/useVoiceMessageInput';
import type { FileType } from '../../platform/types';

export type VoiceMessageInputProps = {
onClose: () => void; // stop playing, recording, hide view
onClose: () => Promise<void>; // stop playing, recording, hide view
onSend: (params: { file: FileType; duration: number }) => void;
};

const VoiceMessageInput = ({ onClose, onSend }: VoiceMessageInputProps) => {
const { STRINGS } = useLocalization();
const { colors } = useUIKitTheme();
const { actions, state } = useVoiceMessageInput((file, duration) => onSend({ file, duration }));
const { actions, state } = useVoiceMessageInput({
onSend: (file, duration) => onSend({ file, duration }),
onClose,
});

const uiColors = colors.ui.voiceMessageInput.default[state.status !== 'idle' ? 'active' : 'inactive'];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ export interface VoiceMessageInputResult {
state: State;
}

const useVoiceMessageInput = (onSend: (voiceFile: FileType, duration: number) => void): VoiceMessageInputResult => {
type Props = {
onClose: () => Promise<void>;
onSend: (voiceFile: FileType, duration: number) => void;
};

const useVoiceMessageInput = ({ onSend, onClose }: Props): VoiceMessageInputResult => {
const { alert } = useAlert();
const { STRINGS } = useLocalization();
const { recorderService, playerService, fileService } = usePlatformService();
Expand Down Expand Up @@ -109,6 +114,7 @@ const useVoiceMessageInput = (onSend: (voiceFile: FileType, duration: number) =>
async startRecording() {
const granted = await recorderService.requestPermission();
if (!granted) {
await onClose();
alert({
title: STRINGS.DIALOG.ALERT_PERMISSIONS_TITLE,
message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
Expand Down
25 changes: 24 additions & 1 deletion packages/uikit-utils/src/hooks/react-native.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useRef } from 'react';
import { useEffect, useRef, useState } from 'react';
import { AppState, AppStateEvent, AppStateStatus } from 'react-native';
import { EdgeInsets, useSafeAreaInsets } from 'react-native-safe-area-context';

Expand Down Expand Up @@ -44,3 +44,26 @@ export const useAppState = (type: AppStateEvent, listener: AppStateListener) =>
};
}, []);
};

/**
* To display a new modal in React-Native, you should ensure that a new modal is opened only after the existing modal has been dismissed to avoid conflicts.
* To achieve this, you can use a deferred onClose that can be awaited until the onDismiss is called.
* */
export const useDeferredModalState = () => {
const resolveRef = useRef<(value: void) => void>();
const [visible, setVisible] = useState(false);

return {
onClose: () => {
return new Promise<void>((resolve) => {
resolveRef.current = resolve;
setVisible(false);
});
},
onDismiss: () => {
resolveRef.current?.();
},
visible,
setVisible,
};
};

0 comments on commit 62ef277

Please sign in to comment.