import React, {useRef, useEffect} from 'react' import {StyleSheet} from 'react-native' import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context' import {observer} from 'mobx-react-lite' import BottomSheet from '@gorhom/bottom-sheet' import {useStores} from 'state/index' import {createCustomBackdrop} from '../util/BottomSheetCustomBackdrop' import {usePalette} from 'lib/hooks/usePalette' import {timeout} from 'lib/async/timeout' import {navigate} from '../../../Navigation' import once from 'lodash.once' import * as ConfirmModal from './Confirm' import * as EditProfileModal from './EditProfile' import * as ProfilePreviewModal from './ProfilePreview' import * as ServerInputModal from './ServerInput' import * as RepostModal from './Repost' import * as SelfLabelModal from './SelfLabel' import * as CreateOrEditListModal from './CreateOrEditList' import * as UserAddRemoveListsModal from './UserAddRemoveLists' import * as ListAddUserModal from './ListAddUser' import * as AltImageModal from './AltImage' import * as EditImageModal from './AltImage' import * as ReportModal from './report/Modal' import * as DeleteAccountModal from './DeleteAccount' import * as ChangeHandleModal from './ChangeHandle' import * as WaitlistModal from './Waitlist' import * as InviteCodesModal from './InviteCodes' import * as AddAppPassword from './AddAppPasswords' import * as ContentFilteringSettingsModal from './ContentFilteringSettings' import * as ContentLanguagesSettingsModal from './lang-settings/ContentLanguagesSettings' import * as PostLanguagesSettingsModal from './lang-settings/PostLanguagesSettings' import * as ModerationDetailsModal from './ModerationDetails' import * as BirthDateSettingsModal from './BirthDateSettings' import * as VerifyEmailModal from './VerifyEmail' import * as ChangeEmailModal from './ChangeEmail' import * as SwitchAccountModal from './SwitchAccount' import * as LinkWarningModal from './LinkWarning' const DEFAULT_SNAPPOINTS = ['90%'] const HANDLE_HEIGHT = 24 export const ModalsContainer = observer(function ModalsContainer() { const store = useStores() const bottomSheetRef = useRef(null) const pal = usePalette('default') const safeAreaInsets = useSafeAreaInsets() const activeModal = store.shell.activeModals[store.shell.activeModals.length - 1] const navigateOnce = once(navigate) const onBottomSheetAnimate = (fromIndex: number, toIndex: number) => { if (activeModal?.name === 'profile-preview' && toIndex === 1) { // begin loading the profile screen behind the scenes navigateOnce('Profile', {name: activeModal.did}) } } const onBottomSheetChange = async (snapPoint: number) => { if (snapPoint === -1) { store.shell.closeModal() } else if (activeModal?.name === 'profile-preview' && snapPoint === 1) { await navigateOnce('Profile', {name: activeModal.did}) // There is no particular callback for when the view has actually been presented. // This delay gives us a decent chance the navigation has flushed *and* images have loaded. // It's acceptable because the data is already being fetched + it usually takes longer anyway. // TODO: Figure out why avatar/cover don't always show instantly from cache. await timeout(200) store.shell.closeModal() } } const onClose = () => { bottomSheetRef.current?.close() store.shell.closeModal() } useEffect(() => { if (store.shell.isModalActive) { bottomSheetRef.current?.expand() } else { bottomSheetRef.current?.close() } }, [store.shell.isModalActive, bottomSheetRef, activeModal?.name]) let needsSafeTopInset = false let snapPoints: (string | number)[] = DEFAULT_SNAPPOINTS let element if (activeModal?.name === 'confirm') { snapPoints = ConfirmModal.snapPoints element = } else if (activeModal?.name === 'edit-profile') { snapPoints = EditProfileModal.snapPoints element = } else if (activeModal?.name === 'profile-preview') { snapPoints = ProfilePreviewModal.snapPoints element = needsSafeTopInset = true // Need to align with the target profile screen. } else if (activeModal?.name === 'server-input') { snapPoints = ServerInputModal.snapPoints element = } else if (activeModal?.name === 'report') { snapPoints = ReportModal.snapPoints element = } else if (activeModal?.name === 'create-or-edit-list') { snapPoints = CreateOrEditListModal.snapPoints element = } else if (activeModal?.name === 'user-add-remove-lists') { snapPoints = UserAddRemoveListsModal.snapPoints element = } else if (activeModal?.name === 'list-add-user') { snapPoints = ListAddUserModal.snapPoints element = } else if (activeModal?.name === 'delete-account') { snapPoints = DeleteAccountModal.snapPoints element = } else if (activeModal?.name === 'repost') { snapPoints = RepostModal.snapPoints element = } else if (activeModal?.name === 'self-label') { snapPoints = SelfLabelModal.snapPoints element = } else if (activeModal?.name === 'alt-text-image') { snapPoints = AltImageModal.snapPoints element = } else if (activeModal?.name === 'edit-image') { snapPoints = AltImageModal.snapPoints element = } else if (activeModal?.name === 'change-handle') { snapPoints = ChangeHandleModal.snapPoints element = } else if (activeModal?.name === 'waitlist') { snapPoints = WaitlistModal.snapPoints element = } else if (activeModal?.name === 'invite-codes') { snapPoints = InviteCodesModal.snapPoints element = } else if (activeModal?.name === 'add-app-password') { snapPoints = AddAppPassword.snapPoints element = } else if (activeModal?.name === 'content-filtering-settings') { snapPoints = ContentFilteringSettingsModal.snapPoints element = } else if (activeModal?.name === 'content-languages-settings') { snapPoints = ContentLanguagesSettingsModal.snapPoints element = } else if (activeModal?.name === 'post-languages-settings') { snapPoints = PostLanguagesSettingsModal.snapPoints element = } else if (activeModal?.name === 'moderation-details') { snapPoints = ModerationDetailsModal.snapPoints element = } else if (activeModal?.name === 'birth-date-settings') { snapPoints = BirthDateSettingsModal.snapPoints element = } else if (activeModal?.name === 'verify-email') { snapPoints = VerifyEmailModal.snapPoints element = } else if (activeModal?.name === 'change-email') { snapPoints = ChangeEmailModal.snapPoints element = } else if (activeModal?.name === 'switch-account') { snapPoints = SwitchAccountModal.snapPoints element = } else if (activeModal?.name === 'link-warning') { snapPoints = LinkWarningModal.snapPoints element = } else { return null } if (snapPoints[0] === 'fullscreen') { return ( {element} ) } const topInset = needsSafeTopInset ? safeAreaInsets.top - HANDLE_HEIGHT : 0 return ( {element} ) }) const styles = StyleSheet.create({ handle: { borderTopLeftRadius: 10, borderTopRightRadius: 10, }, fullscreenContainer: { position: 'absolute', top: 0, left: 0, bottom: 0, right: 0, }, })