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