mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {StyleSheet, View} from 'react-native'
3import {DismissableLayer} from '@radix-ui/react-dismissable-layer'
4import {useFocusGuards} from '@radix-ui/react-focus-guards'
5import {FocusScope} from '@radix-ui/react-focus-scope'
6
7import {useWebBodyScrollLock} from '#/lib/hooks/useWebBodyScrollLock'
8import {useModals} from '#/state/modals'
9import {ComposerOpts, useComposerState} from '#/state/shell/composer'
10import {
11 EmojiPicker,
12 EmojiPickerState,
13} from '#/view/com/composer/text-input/web/EmojiPicker.web'
14import {useBreakpoints, useTheme} from '#/alf'
15import {ComposePost, useComposerCancelRef} from '../com/composer/Composer'
16
17const BOTTOM_BAR_HEIGHT = 61
18
19export function Composer({}: {winHeight: number}) {
20 const state = useComposerState()
21 const isActive = !!state
22
23 useWebBodyScrollLock(isActive)
24
25 // rendering
26 // =
27
28 if (!isActive) {
29 return <View />
30 }
31
32 return <Inner state={state} />
33}
34
35function Inner({state}: {state: ComposerOpts}) {
36 const ref = useComposerCancelRef()
37 const {isModalActive} = useModals()
38 const t = useTheme()
39 const {gtMobile} = useBreakpoints()
40 const [pickerState, setPickerState] = React.useState<EmojiPickerState>({
41 isOpen: false,
42 pos: {top: 0, left: 0, right: 0, bottom: 0},
43 })
44
45 const onOpenPicker = React.useCallback((pos: DOMRect | undefined) => {
46 if (!pos) return
47 setPickerState({
48 isOpen: true,
49 pos,
50 })
51 }, [])
52
53 const onClosePicker = React.useCallback(() => {
54 setPickerState(prev => ({
55 ...prev,
56 isOpen: false,
57 }))
58 }, [])
59
60 useFocusGuards()
61
62 return (
63 <FocusScope loop trapped asChild>
64 <DismissableLayer
65 role="dialog"
66 aria-modal
67 style={{
68 position: 'fixed',
69 top: 0,
70 left: 0,
71 width: '100%',
72 height: '100%',
73 backgroundColor: '#000c',
74 display: 'flex',
75 flexDirection: 'column',
76 alignItems: 'center',
77 }}
78 onFocusOutside={evt => evt.preventDefault()}
79 onInteractOutside={evt => evt.preventDefault()}
80 onDismiss={() => {
81 // TEMP: remove when all modals are ALF'd -sfn
82 if (!isModalActive) {
83 ref.current?.onPressCancel()
84 }
85 }}>
86 <View
87 style={[
88 styles.container,
89 !gtMobile && styles.containerMobile,
90 t.atoms.bg,
91 t.atoms.border_contrast_medium,
92 ]}>
93 <ComposePost
94 cancelRef={ref}
95 replyTo={state.replyTo}
96 quote={state.quote}
97 onPost={state.onPost}
98 mention={state.mention}
99 openEmojiPicker={onOpenPicker}
100 text={state.text}
101 imageUris={state.imageUris}
102 />
103 </View>
104 <EmojiPicker state={pickerState} close={onClosePicker} />
105 </DismissableLayer>
106 </FocusScope>
107 )
108}
109
110const styles = StyleSheet.create({
111 container: {
112 marginTop: 50,
113 maxWidth: 600,
114 width: '100%',
115 paddingVertical: 0,
116 borderRadius: 8,
117 marginBottom: 0,
118 borderWidth: 1,
119 // @ts-ignore web only
120 maxHeight: 'calc(100% - (40px * 2))',
121 overflow: 'hidden',
122 },
123 containerMobile: {
124 borderRadius: 0,
125 marginBottom: BOTTOM_BAR_HEIGHT,
126 // @ts-ignore web only
127 maxHeight: `calc(100% - ${BOTTOM_BAR_HEIGHT}px)`,
128 },
129})