mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native'
3import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
4
5import {useWebBodyScrollLock} from '#/lib/hooks/useWebBodyScrollLock'
6import type {Modal as ModalIface} from '#/state/modals'
7import {useModalControls, useModals} from '#/state/modals'
8import {usePalette} from 'lib/hooks/usePalette'
9import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
10import * as AddAppPassword from './AddAppPasswords'
11import * as AltTextImageModal from './AltImage'
12import * as ChangeEmailModal from './ChangeEmail'
13import * as ChangeHandleModal from './ChangeHandle'
14import * as ChangePasswordModal from './ChangePassword'
15import * as CreateOrEditListModal from './CreateOrEditList'
16import * as CropImageModal from './crop-image/CropImage.web'
17import * as DeleteAccountModal from './DeleteAccount'
18import * as EditImageModal from './EditImage'
19import * as EditProfileModal from './EditProfile'
20import * as InviteCodesModal from './InviteCodes'
21import * as ContentLanguagesSettingsModal from './lang-settings/ContentLanguagesSettings'
22import * as PostLanguagesSettingsModal from './lang-settings/PostLanguagesSettings'
23import * as LinkWarningModal from './LinkWarning'
24import * as ListAddUserModal from './ListAddRemoveUsers'
25import * as SelfLabelModal from './SelfLabel'
26import * as UserAddRemoveLists from './UserAddRemoveLists'
27import * as VerifyEmailModal from './VerifyEmail'
28
29export function ModalsContainer() {
30 const {isModalActive, activeModals} = useModals()
31 useWebBodyScrollLock(isModalActive)
32
33 if (!isModalActive) {
34 return null
35 }
36
37 return (
38 <>
39 {activeModals.map((modal, i) => (
40 <Modal key={`modal-${i}`} modal={modal} />
41 ))}
42 </>
43 )
44}
45
46function Modal({modal}: {modal: ModalIface}) {
47 const {isModalActive} = useModals()
48 const {closeModal} = useModalControls()
49 const pal = usePalette('default')
50 const {isMobile} = useWebMediaQueries()
51
52 if (!isModalActive) {
53 return null
54 }
55
56 const onPressMask = () => {
57 if (
58 modal.name === 'crop-image' ||
59 modal.name === 'edit-image' ||
60 modal.name === 'alt-text-image'
61 ) {
62 return // dont close on mask presses during crop
63 }
64 closeModal()
65 }
66 const onInnerPress = () => {
67 // TODO: can we use prevent default?
68 // do nothing, we just want to stop it from bubbling
69 }
70
71 let element
72 if (modal.name === 'edit-profile') {
73 element = <EditProfileModal.Component {...modal} />
74 } else if (modal.name === 'create-or-edit-list') {
75 element = <CreateOrEditListModal.Component {...modal} />
76 } else if (modal.name === 'user-add-remove-lists') {
77 element = <UserAddRemoveLists.Component {...modal} />
78 } else if (modal.name === 'list-add-remove-users') {
79 element = <ListAddUserModal.Component {...modal} />
80 } else if (modal.name === 'crop-image') {
81 element = <CropImageModal.Component {...modal} />
82 } else if (modal.name === 'delete-account') {
83 element = <DeleteAccountModal.Component />
84 } else if (modal.name === 'self-label') {
85 element = <SelfLabelModal.Component {...modal} />
86 } else if (modal.name === 'change-handle') {
87 element = <ChangeHandleModal.Component {...modal} />
88 } else if (modal.name === 'invite-codes') {
89 element = <InviteCodesModal.Component />
90 } else if (modal.name === 'add-app-password') {
91 element = <AddAppPassword.Component />
92 } else if (modal.name === 'content-languages-settings') {
93 element = <ContentLanguagesSettingsModal.Component />
94 } else if (modal.name === 'post-languages-settings') {
95 element = <PostLanguagesSettingsModal.Component />
96 } else if (modal.name === 'alt-text-image') {
97 element = <AltTextImageModal.Component {...modal} />
98 } else if (modal.name === 'edit-image') {
99 element = <EditImageModal.Component {...modal} />
100 } else if (modal.name === 'verify-email') {
101 element = <VerifyEmailModal.Component {...modal} />
102 } else if (modal.name === 'change-email') {
103 element = <ChangeEmailModal.Component />
104 } else if (modal.name === 'change-password') {
105 element = <ChangePasswordModal.Component />
106 } else if (modal.name === 'link-warning') {
107 element = <LinkWarningModal.Component {...modal} />
108 } else {
109 return null
110 }
111
112 return (
113 // eslint-disable-next-line react-native-a11y/has-valid-accessibility-descriptors
114 <TouchableWithoutFeedback onPress={onPressMask}>
115 <Animated.View
116 style={styles.mask}
117 entering={FadeIn.duration(150)}
118 exiting={FadeOut}>
119 {/* eslint-disable-next-line react-native-a11y/has-valid-accessibility-descriptors */}
120 <TouchableWithoutFeedback onPress={onInnerPress}>
121 <View
122 style={[
123 styles.container,
124 isMobile && styles.containerMobile,
125 pal.view,
126 pal.border,
127 ]}>
128 {element}
129 </View>
130 </TouchableWithoutFeedback>
131 </Animated.View>
132 </TouchableWithoutFeedback>
133 )
134}
135
136const styles = StyleSheet.create({
137 mask: {
138 // @ts-ignore
139 position: 'fixed',
140 top: 0,
141 left: 0,
142 width: '100%',
143 height: '100%',
144 backgroundColor: '#000c',
145 alignItems: 'center',
146 justifyContent: 'center',
147 },
148 container: {
149 width: 600,
150 // @ts-ignore web only
151 maxWidth: '100vw',
152 // @ts-ignore web only
153 maxHeight: '90vh',
154 paddingVertical: 20,
155 paddingHorizontal: 24,
156 borderRadius: 8,
157 borderWidth: 1,
158 },
159 containerMobile: {
160 borderRadius: 0,
161 paddingHorizontal: 0,
162 },
163})