Bluesky app fork with some witchin' additions 馃挮
witchsky.app
bluesky
fork
client
1import {StyleSheet, View} from 'react-native'
2import {DismissableLayer, FocusGuards, FocusScope} from 'radix-ui/internal'
3import {RemoveScrollBar} from 'react-remove-scroll-bar'
4
5import {useA11y} from '#/state/a11y'
6import {useModals} from '#/state/modals'
7import {type ComposerOpts, useComposerState} from '#/state/shell/composer'
8import {atoms as a, flatten, useBreakpoints, useTheme} from '#/alf'
9import {ComposePost, useComposerCancelRef} from '../com/composer/Composer'
10
11const BOTTOM_BAR_HEIGHT = 61
12
13export function Composer({}: {winHeight: number}) {
14 const state = useComposerState()
15 const isActive = !!state
16
17 // rendering
18 // =
19
20 if (!isActive) {
21 return null
22 }
23
24 return (
25 <>
26 <RemoveScrollBar />
27 <Inner state={state} />
28 </>
29 )
30}
31
32function Inner({state}: {state: ComposerOpts}) {
33 const ref = useComposerCancelRef()
34 const {isModalActive} = useModals()
35 const t = useTheme()
36 const {gtMobile} = useBreakpoints()
37 const {reduceMotionEnabled} = useA11y()
38
39 FocusGuards.useFocusGuards()
40
41 return (
42 <FocusScope.FocusScope loop trapped asChild>
43 <DismissableLayer.DismissableLayer
44 role="dialog"
45 aria-modal
46 style={flatten([
47 {position: 'fixed'},
48 a.inset_0,
49 {backgroundColor: '#000c'},
50 a.flex,
51 a.flex_col,
52 a.align_center,
53 !reduceMotionEnabled && a.fade_in,
54 ])}
55 onFocusOutside={evt => evt.preventDefault()}
56 onInteractOutside={evt => evt.preventDefault()}
57 onDismiss={() => {
58 // TEMP: remove when all modals are ALF'd -sfn
59 if (!isModalActive) {
60 ref.current?.onPressCancel()
61 }
62 }}>
63 <View
64 style={[
65 styles.container,
66 !gtMobile && styles.containerMobile,
67 t.atoms.bg,
68 t.atoms.border_contrast_medium,
69 !reduceMotionEnabled && [
70 a.zoom_fade_in,
71 {animationDelay: 0.1},
72 {animationFillMode: 'backwards'},
73 ],
74 ]}>
75 <ComposePost
76 cancelRef={ref}
77 replyTo={state.replyTo}
78 quote={state.quote}
79 onPost={state.onPost}
80 onPostSuccess={state.onPostSuccess}
81 mention={state.mention}
82 text={state.text}
83 imageUris={state.imageUris}
84 videoUri={state.videoUri}
85 openGallery={state.openGallery}
86 />
87 </View>
88 </DismissableLayer.DismissableLayer>
89 </FocusScope.FocusScope>
90 )
91}
92
93const styles = StyleSheet.create({
94 container: {
95 marginTop: 50,
96 maxWidth: 600,
97 width: '100%',
98 paddingVertical: 0,
99 borderRadius: 8,
100 marginBottom: 0,
101 borderWidth: 1,
102 // @ts-expect-error web only
103 maxHeight: 'calc(100% - (40px * 2))',
104 overflow: 'hidden',
105 },
106 containerMobile: {
107 borderRadius: 0,
108 marginBottom: BOTTOM_BAR_HEIGHT,
109 // @ts-expect-error web only
110 maxHeight: `calc(100% - ${BOTTOM_BAR_HEIGHT}px)`,
111 },
112})