forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native'
2import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
3import {RemoveScrollBar} from 'react-remove-scroll-bar'
4
5import {usePalette} from '#/lib/hooks/usePalette'
6import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
7import {type Modal as ModalIface} from '#/state/modals'
8import {useModalControls, useModals} from '#/state/modals'
9import * as DeleteAccountModal from './DeleteAccount'
10import * as ContentLanguagesSettingsModal from './lang-settings/ContentLanguagesSettings'
11import * as UserAddRemoveLists from './UserAddRemoveLists'
12
13export function ModalsContainer() {
14 const {isModalActive, activeModals} = useModals()
15
16 if (!isModalActive) {
17 return null
18 }
19
20 return (
21 <>
22 <RemoveScrollBar />
23 {activeModals.map((modal, i) => (
24 <Modal key={`modal-${i}`} modal={modal} />
25 ))}
26 </>
27 )
28}
29
30function Modal({modal}: {modal: ModalIface}) {
31 const {isModalActive} = useModals()
32 const {closeModal} = useModalControls()
33 const pal = usePalette('default')
34 const {isMobile} = useWebMediaQueries()
35
36 if (!isModalActive) {
37 return null
38 }
39
40 const onPressMask = () => {
41 closeModal()
42 }
43 const onInnerPress = () => {
44 // TODO: can we use prevent default?
45 // do nothing, we just want to stop it from bubbling
46 }
47
48 let element
49 if (modal.name === 'user-add-remove-lists') {
50 element = <UserAddRemoveLists.Component {...modal} />
51 } else if (modal.name === 'delete-account') {
52 element = <DeleteAccountModal.Component />
53 } else if (modal.name === 'content-languages-settings') {
54 element = <ContentLanguagesSettingsModal.Component />
55 } else {
56 return null
57 }
58
59 return (
60 // eslint-disable-next-line react-native-a11y/has-valid-accessibility-descriptors
61 <TouchableWithoutFeedback onPress={onPressMask}>
62 <Animated.View
63 style={styles.mask}
64 entering={FadeIn.duration(150)}
65 exiting={FadeOut}>
66 {/* eslint-disable-next-line react-native-a11y/has-valid-accessibility-descriptors */}
67 <TouchableWithoutFeedback onPress={onInnerPress}>
68 <View
69 style={[
70 styles.container,
71 isMobile && styles.containerMobile,
72 pal.view,
73 pal.border,
74 ]}>
75 {element}
76 </View>
77 </TouchableWithoutFeedback>
78 </Animated.View>
79 </TouchableWithoutFeedback>
80 )
81}
82
83const styles = StyleSheet.create({
84 mask: {
85 // @ts-ignore
86 position: 'fixed',
87 top: 0,
88 left: 0,
89 width: '100%',
90 height: '100%',
91 backgroundColor: '#000c',
92 alignItems: 'center',
93 justifyContent: 'center',
94 },
95 container: {
96 width: 600,
97 // @ts-ignore web only
98 maxWidth: '100vw',
99 // @ts-ignore web only
100 maxHeight: '90vh',
101 paddingVertical: 20,
102 paddingHorizontal: 24,
103 borderRadius: 8,
104 borderWidth: 1,
105 },
106 containerMobile: {
107 borderRadius: 0,
108 paddingHorizontal: 0,
109 },
110})