diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/App.native.tsx | 19 | ||||
-rw-r--r-- | src/components/Dialog/index.tsx | 31 | ||||
-rw-r--r-- | src/components/dialogs/GifSelect.tsx | 4 | ||||
-rw-r--r-- | src/components/dialogs/MutedWords.tsx | 528 | ||||
-rw-r--r-- | src/components/dialogs/PostInteractionSettingsDialog.tsx | 9 | ||||
-rw-r--r-- | src/state/dialogs/index.tsx | 4 | ||||
-rw-r--r-- | src/view/com/composer/Composer.tsx | 20 | ||||
-rw-r--r-- | src/view/com/composer/GifAltText.tsx | 9 | ||||
-rw-r--r-- | src/view/com/composer/photos/Gallery.tsx | 13 | ||||
-rw-r--r-- | src/view/com/composer/photos/ImageAltTextDialog.tsx | 6 | ||||
-rw-r--r-- | src/view/com/composer/photos/SelectGifBtn.tsx | 5 | ||||
-rw-r--r-- | src/view/com/composer/threadgate/ThreadgateBtn.tsx | 5 | ||||
-rw-r--r-- | src/view/com/composer/videos/SubtitleDialog.tsx | 4 | ||||
-rw-r--r-- | src/view/screens/Storybook/Dialogs.tsx | 66 | ||||
-rw-r--r-- | src/view/shell/index.tsx | 2 |
15 files changed, 311 insertions, 414 deletions
diff --git a/src/App.native.tsx b/src/App.native.tsx index 96b493af4..0b9f112ee 100644 --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -68,6 +68,7 @@ import {useStarterPackEntry} from '#/components/hooks/useStarterPackEntry' import {Provider as IntentDialogProvider} from '#/components/intents/IntentDialogs' import {Provider as PortalProvider} from '#/components/Portal' import {Splash} from '#/Splash' +import {BottomSheetProvider} from '../modules/bottom-sheet' import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider' SplashScreen.preventAutoHideAsync() @@ -197,14 +198,16 @@ function App() { <DialogStateProvider> <LightboxStateProvider> <PortalProvider> - <StarterPackProvider> - <SafeAreaProvider - initialMetrics={initialWindowMetrics}> - <IntentDialogProvider> - <InnerApp /> - </IntentDialogProvider> - </SafeAreaProvider> - </StarterPackProvider> + <BottomSheetProvider> + <StarterPackProvider> + <SafeAreaProvider + initialMetrics={initialWindowMetrics}> + <IntentDialogProvider> + <InnerApp /> + </IntentDialogProvider> + </SafeAreaProvider> + </StarterPackProvider> + </BottomSheetProvider> </PortalProvider> </LightboxStateProvider> </DialogStateProvider> diff --git a/src/components/Dialog/index.tsx b/src/components/Dialog/index.tsx index 49b5e10b2..6d859aeb0 100644 --- a/src/components/Dialog/index.tsx +++ b/src/components/Dialog/index.tsx @@ -31,12 +31,12 @@ import { DialogOuterProps, } from '#/components/Dialog/types' import {createInput} from '#/components/forms/TextField' -import {Portal as DefaultPortal} from '#/components/Portal' import {BottomSheet, BottomSheetSnapPoint} from '../../../modules/bottom-sheet' import { BottomSheetSnapPointChangeEvent, BottomSheetStateChangeEvent, } from '../../../modules/bottom-sheet/src/BottomSheet.types' +import {BottomSheetNativeComponent} from '../../../modules/bottom-sheet/src/BottomSheetNativeComponent' export {useDialogContext, useDialogControl} from '#/components/Dialog/context' export * from '#/components/Dialog/types' @@ -50,10 +50,9 @@ export function Outer({ onClose, nativeOptions, testID, - Portal = DefaultPortal, }: React.PropsWithChildren<DialogOuterProps>) { const t = useTheme() - const ref = React.useRef<BottomSheet>(null) + const ref = React.useRef<BottomSheetNativeComponent>(null) const closeCallbacks = React.useRef<(() => void)[]>([]) const {setDialogIsOpen, setFullyExpandedCount} = useDialogStateControlContext() @@ -154,20 +153,18 @@ export function Outer({ ) return ( - <Portal> - <Context.Provider value={context}> - <BottomSheet - ref={ref} - cornerRadius={20} - backgroundColor={t.atoms.bg.backgroundColor} - {...nativeOptions} - onSnapPointChange={onSnapPointChange} - onStateChange={onStateChange} - disableDrag={disableDrag}> - <View testID={testID}>{children}</View> - </BottomSheet> - </Context.Provider> - </Portal> + <Context.Provider value={context}> + <BottomSheet + ref={ref} + cornerRadius={20} + backgroundColor={t.atoms.bg.backgroundColor} + {...nativeOptions} + onSnapPointChange={onSnapPointChange} + onStateChange={onStateChange} + disableDrag={disableDrag}> + <View testID={testID}>{children}</View> + </BottomSheet> + </Context.Provider> ) } diff --git a/src/components/dialogs/GifSelect.tsx b/src/components/dialogs/GifSelect.tsx index c0ed202da..765e9415d 100644 --- a/src/components/dialogs/GifSelect.tsx +++ b/src/components/dialogs/GifSelect.tsx @@ -30,18 +30,15 @@ import {useThrottledValue} from '#/components/hooks/useThrottledValue' import {ArrowLeft_Stroke2_Corner0_Rounded as Arrow} from '#/components/icons/Arrow' import {MagnifyingGlass2_Stroke2_Corner0_Rounded as Search} from '#/components/icons/MagnifyingGlass2' import {ListFooter, ListMaybePlaceholder} from '#/components/Lists' -import {PortalComponent} from '#/components/Portal' export function GifSelectDialog({ controlRef, onClose, onSelectGif: onSelectGifProp, - Portal, }: { controlRef: React.RefObject<{open: () => void}> onClose: () => void onSelectGif: (gif: Gif) => void - Portal?: PortalComponent }) { const control = Dialog.useDialogControl() @@ -65,7 +62,6 @@ export function GifSelectDialog({ <Dialog.Outer control={control} onClose={onClose} - Portal={Portal} nativeOptions={{ bottomInset: 0, // use system corner radius on iOS diff --git a/src/components/dialogs/MutedWords.tsx b/src/components/dialogs/MutedWords.tsx index c3aae8f0d..81a614103 100644 --- a/src/components/dialogs/MutedWords.tsx +++ b/src/components/dialogs/MutedWords.tsx @@ -30,14 +30,11 @@ import {PageText_Stroke2_Corner0_Rounded as PageText} from '#/components/icons/P import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' import {Loader} from '#/components/Loader' -import {createPortalGroup} from '#/components/Portal' import * as Prompt from '#/components/Prompt' import {Text} from '#/components/Typography' const ONE_DAY = 24 * 60 * 60 * 1000 -const Portal = createPortalGroup() - export function MutedWordsDialog() { const {mutedWordsDialogControl: control} = useGlobalDialogsControlContext() return ( @@ -108,349 +105,307 @@ function MutedWordsInner() { }, [_, field, targets, addMutedWord, setField, durations, excludeFollowing]) return ( - <Portal.Provider> - <Dialog.ScrollableInner label={_(msg`Manage your muted words and tags`)}> - <View> - <Text - style={[ - a.text_md, - a.font_bold, - a.pb_sm, - t.atoms.text_contrast_high, - ]}> - <Trans>Add muted words and tags</Trans> - </Text> - <Text style={[a.pb_lg, a.leading_snug, t.atoms.text_contrast_medium]}> - <Trans> - Posts can be muted based on their text, their tags, or both. We - recommend avoiding common words that appear in many posts, since - it can result in no posts being shown. - </Trans> - </Text> - - <View style={[a.pb_sm]}> - <Dialog.Input - autoCorrect={false} - autoCapitalize="none" - autoComplete="off" - label={_(msg`Enter a word or tag`)} - placeholder={_(msg`Enter a word or tag`)} - value={field} - onChangeText={value => { - if (error) { - setError('') - } - setField(value) - }} - onSubmitEditing={submit} - /> - </View> + <Dialog.ScrollableInner label={_(msg`Manage your muted words and tags`)}> + <View> + <Text + style={[a.text_md, a.font_bold, a.pb_sm, t.atoms.text_contrast_high]}> + <Trans>Add muted words and tags</Trans> + </Text> + <Text style={[a.pb_lg, a.leading_snug, t.atoms.text_contrast_medium]}> + <Trans> + Posts can be muted based on their text, their tags, or both. We + recommend avoiding common words that appear in many posts, since it + can result in no posts being shown. + </Trans> + </Text> + + <View style={[a.pb_sm]}> + <Dialog.Input + autoCorrect={false} + autoCapitalize="none" + autoComplete="off" + label={_(msg`Enter a word or tag`)} + placeholder={_(msg`Enter a word or tag`)} + value={field} + onChangeText={value => { + if (error) { + setError('') + } + setField(value) + }} + onSubmitEditing={submit} + /> + </View> - <View style={[a.pb_xl, a.gap_sm]}> - <Toggle.Group - label={_(msg`Select how long to mute this word for.`)} - type="radio" - values={durations} - onChange={setDurations}> - <Text - style={[ - a.pb_xs, - a.text_sm, - a.font_bold, - t.atoms.text_contrast_medium, - ]}> - <Trans>Duration:</Trans> - </Text> + <View style={[a.pb_xl, a.gap_sm]}> + <Toggle.Group + label={_(msg`Select how long to mute this word for.`)} + type="radio" + values={durations} + onChange={setDurations}> + <Text + style={[ + a.pb_xs, + a.text_sm, + a.font_bold, + t.atoms.text_contrast_medium, + ]}> + <Trans>Duration:</Trans> + </Text> + <View + style={[ + gtMobile && [a.flex_row, a.align_center, a.justify_start], + a.gap_sm, + ]}> <View style={[ - gtMobile && [a.flex_row, a.align_center, a.justify_start], + a.flex_1, + a.flex_row, + a.justify_start, + a.align_center, a.gap_sm, ]}> - <View - style={[ - a.flex_1, - a.flex_row, - a.justify_start, - a.align_center, - a.gap_sm, - ]}> - <Toggle.Item - label={_(msg`Mute this word until you unmute it`)} - name="forever" - style={[a.flex_1]}> - <TargetToggle> - <View - style={[ - a.flex_1, - a.flex_row, - a.align_center, - a.gap_sm, - ]}> - <Toggle.Radio /> - <Toggle.LabelText style={[a.flex_1, a.leading_tight]}> - <Trans>Forever</Trans> - </Toggle.LabelText> - </View> - </TargetToggle> - </Toggle.Item> - - <Toggle.Item - label={_(msg`Mute this word for 24 hours`)} - name="24_hours" - style={[a.flex_1]}> - <TargetToggle> - <View - style={[ - a.flex_1, - a.flex_row, - a.align_center, - a.gap_sm, - ]}> - <Toggle.Radio /> - <Toggle.LabelText style={[a.flex_1, a.leading_tight]}> - <Trans>24 hours</Trans> - </Toggle.LabelText> - </View> - </TargetToggle> - </Toggle.Item> - </View> + <Toggle.Item + label={_(msg`Mute this word until you unmute it`)} + name="forever" + style={[a.flex_1]}> + <TargetToggle> + <View + style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}> + <Toggle.Radio /> + <Toggle.LabelText style={[a.flex_1, a.leading_tight]}> + <Trans>Forever</Trans> + </Toggle.LabelText> + </View> + </TargetToggle> + </Toggle.Item> - <View - style={[ - a.flex_1, - a.flex_row, - a.justify_start, - a.align_center, - a.gap_sm, - ]}> - <Toggle.Item - label={_(msg`Mute this word for 7 days`)} - name="7_days" - style={[a.flex_1]}> - <TargetToggle> - <View - style={[ - a.flex_1, - a.flex_row, - a.align_center, - a.gap_sm, - ]}> - <Toggle.Radio /> - <Toggle.LabelText style={[a.flex_1, a.leading_tight]}> - <Trans>7 days</Trans> - </Toggle.LabelText> - </View> - </TargetToggle> - </Toggle.Item> - - <Toggle.Item - label={_(msg`Mute this word for 30 days`)} - name="30_days" - style={[a.flex_1]}> - <TargetToggle> - <View - style={[ - a.flex_1, - a.flex_row, - a.align_center, - a.gap_sm, - ]}> - <Toggle.Radio /> - <Toggle.LabelText style={[a.flex_1, a.leading_tight]}> - <Trans>30 days</Trans> - </Toggle.LabelText> - </View> - </TargetToggle> - </Toggle.Item> - </View> + <Toggle.Item + label={_(msg`Mute this word for 24 hours`)} + name="24_hours" + style={[a.flex_1]}> + <TargetToggle> + <View + style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}> + <Toggle.Radio /> + <Toggle.LabelText style={[a.flex_1, a.leading_tight]}> + <Trans>24 hours</Trans> + </Toggle.LabelText> + </View> + </TargetToggle> + </Toggle.Item> </View> - </Toggle.Group> - <Toggle.Group - label={_( - msg`Select what content this mute word should apply to.`, - )} - type="radio" - values={targets} - onChange={setTargets}> - <Text + <View style={[ - a.pb_xs, - a.text_sm, - a.font_bold, - t.atoms.text_contrast_medium, + a.flex_1, + a.flex_row, + a.justify_start, + a.align_center, + a.gap_sm, ]}> - <Trans>Mute in:</Trans> - </Text> - - <View style={[a.flex_row, a.align_center, a.gap_sm, a.flex_wrap]}> <Toggle.Item - label={_(msg`Mute this word in post text and tags`)} - name="content" + label={_(msg`Mute this word for 7 days`)} + name="7_days" style={[a.flex_1]}> <TargetToggle> <View style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}> <Toggle.Radio /> <Toggle.LabelText style={[a.flex_1, a.leading_tight]}> - <Trans>Text & tags</Trans> + <Trans>7 days</Trans> </Toggle.LabelText> </View> - <PageText size="sm" /> </TargetToggle> </Toggle.Item> <Toggle.Item - label={_(msg`Mute this word in tags only`)} - name="tag" + label={_(msg`Mute this word for 30 days`)} + name="30_days" style={[a.flex_1]}> <TargetToggle> <View style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}> <Toggle.Radio /> <Toggle.LabelText style={[a.flex_1, a.leading_tight]}> - <Trans>Tags only</Trans> + <Trans>30 days</Trans> </Toggle.LabelText> </View> - <Hashtag size="sm" /> </TargetToggle> </Toggle.Item> </View> - </Toggle.Group> + </View> + </Toggle.Group> - <View> - <Text - style={[ - a.pb_xs, - a.text_sm, - a.font_bold, - t.atoms.text_contrast_medium, - ]}> - <Trans>Options:</Trans> - </Text> + <Toggle.Group + label={_(msg`Select what content this mute word should apply to.`)} + type="radio" + values={targets} + onChange={setTargets}> + <Text + style={[ + a.pb_xs, + a.text_sm, + a.font_bold, + t.atoms.text_contrast_medium, + ]}> + <Trans>Mute in:</Trans> + </Text> + + <View style={[a.flex_row, a.align_center, a.gap_sm, a.flex_wrap]}> <Toggle.Item - label={_(msg`Do not apply this mute word to users you follow`)} - name="exclude_following" - style={[a.flex_row, a.justify_between]} - value={excludeFollowing} - onChange={setExcludeFollowing}> + label={_(msg`Mute this word in post text and tags`)} + name="content" + style={[a.flex_1]}> <TargetToggle> <View style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}> - <Toggle.Checkbox /> + <Toggle.Radio /> <Toggle.LabelText style={[a.flex_1, a.leading_tight]}> - <Trans>Exclude users you follow</Trans> + <Trans>Text & tags</Trans> </Toggle.LabelText> </View> + <PageText size="sm" /> </TargetToggle> </Toggle.Item> - </View> - <View style={[a.pt_xs]}> - <Button - disabled={isPending || !field} - label={_(msg`Add mute word for configured settings`)} - size="large" - color="primary" - variant="solid" - style={[]} - onPress={submit}> - <ButtonText> - <Trans>Add</Trans> - </ButtonText> - <ButtonIcon icon={isPending ? Loader : Plus} position="right" /> - </Button> + <Toggle.Item + label={_(msg`Mute this word in tags only`)} + name="tag" + style={[a.flex_1]}> + <TargetToggle> + <View + style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}> + <Toggle.Radio /> + <Toggle.LabelText style={[a.flex_1, a.leading_tight]}> + <Trans>Tags only</Trans> + </Toggle.LabelText> + </View> + <Hashtag size="sm" /> + </TargetToggle> + </Toggle.Item> </View> + </Toggle.Group> - {error && ( - <View - style={[ - a.mb_lg, - a.flex_row, - a.rounded_sm, - a.p_md, - a.mb_xs, - t.atoms.bg_contrast_25, - { - backgroundColor: t.palette.negative_400, - }, - ]}> - <Text - style={[ - a.italic, - {color: t.palette.white}, - native({marginTop: 2}), - ]}> - {error} - </Text> - </View> - )} - </View> - - <Divider /> - - <View style={[a.pt_2xl]}> + <View> <Text style={[ - a.text_md, + a.pb_xs, + a.text_sm, a.font_bold, - a.pb_md, - t.atoms.text_contrast_high, + t.atoms.text_contrast_medium, ]}> - <Trans>Your muted words</Trans> + <Trans>Options:</Trans> </Text> + <Toggle.Item + label={_(msg`Do not apply this mute word to users you follow`)} + name="exclude_following" + style={[a.flex_row, a.justify_between]} + value={excludeFollowing} + onChange={setExcludeFollowing}> + <TargetToggle> + <View style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}> + <Toggle.Checkbox /> + <Toggle.LabelText style={[a.flex_1, a.leading_tight]}> + <Trans>Exclude users you follow</Trans> + </Toggle.LabelText> + </View> + </TargetToggle> + </Toggle.Item> + </View> - {isPreferencesLoading ? ( - <Loader /> - ) : preferencesError || !preferences ? ( - <View - style={[ - a.py_md, - a.px_lg, - a.rounded_md, - t.atoms.bg_contrast_25, - ]}> - <Text style={[a.italic, t.atoms.text_contrast_high]}> - <Trans> - We're sorry, but we weren't able to load your muted words at - this time. Please try again. - </Trans> - </Text> - </View> - ) : preferences.moderationPrefs.mutedWords.length ? ( - [...preferences.moderationPrefs.mutedWords] - .reverse() - .map((word, i) => ( - <MutedWordRow - key={word.value + i} - word={word} - style={[i % 2 === 0 && t.atoms.bg_contrast_25]} - /> - )) - ) : ( - <View + <View style={[a.pt_xs]}> + <Button + disabled={isPending || !field} + label={_(msg`Add mute word for configured settings`)} + size="large" + color="primary" + variant="solid" + style={[]} + onPress={submit}> + <ButtonText> + <Trans>Add</Trans> + </ButtonText> + <ButtonIcon icon={isPending ? Loader : Plus} position="right" /> + </Button> + </View> + + {error && ( + <View + style={[ + a.mb_lg, + a.flex_row, + a.rounded_sm, + a.p_md, + a.mb_xs, + t.atoms.bg_contrast_25, + { + backgroundColor: t.palette.negative_400, + }, + ]}> + <Text style={[ - a.py_md, - a.px_lg, - a.rounded_md, - t.atoms.bg_contrast_25, + a.italic, + {color: t.palette.white}, + native({marginTop: 2}), ]}> - <Text style={[a.italic, t.atoms.text_contrast_high]}> - <Trans>You haven't muted any words or tags yet</Trans> - </Text> - </View> - )} - </View> + {error} + </Text> + </View> + )} + </View> + + <Divider /> - {isNative && <View style={{height: 20}} />} + <View style={[a.pt_2xl]}> + <Text + style={[ + a.text_md, + a.font_bold, + a.pb_md, + t.atoms.text_contrast_high, + ]}> + <Trans>Your muted words</Trans> + </Text> + + {isPreferencesLoading ? ( + <Loader /> + ) : preferencesError || !preferences ? ( + <View + style={[a.py_md, a.px_lg, a.rounded_md, t.atoms.bg_contrast_25]}> + <Text style={[a.italic, t.atoms.text_contrast_high]}> + <Trans> + We're sorry, but we weren't able to load your muted words at + this time. Please try again. + </Trans> + </Text> + </View> + ) : preferences.moderationPrefs.mutedWords.length ? ( + [...preferences.moderationPrefs.mutedWords] + .reverse() + .map((word, i) => ( + <MutedWordRow + key={word.value + i} + word={word} + style={[i % 2 === 0 && t.atoms.bg_contrast_25]} + /> + )) + ) : ( + <View + style={[a.py_md, a.px_lg, a.rounded_md, t.atoms.bg_contrast_25]}> + <Text style={[a.italic, t.atoms.text_contrast_high]}> + <Trans>You haven't muted any words or tags yet</Trans> + </Text> + </View> + )} </View> - <Dialog.Close /> - </Dialog.ScrollableInner> + {isNative && <View style={{height: 20}} />} + </View> - <Portal.Outlet /> - </Portal.Provider> + <Dialog.Close /> + </Dialog.ScrollableInner> ) } @@ -482,7 +437,6 @@ function MutedWordRow({ onConfirm={remove} confirmButtonCta={_(msg`Remove`)} confirmButtonColor="negative" - Portal={Portal.Portal} /> <View diff --git a/src/components/dialogs/PostInteractionSettingsDialog.tsx b/src/components/dialogs/PostInteractionSettingsDialog.tsx index bddc49968..0b8b386d3 100644 --- a/src/components/dialogs/PostInteractionSettingsDialog.tsx +++ b/src/components/dialogs/PostInteractionSettingsDialog.tsx @@ -37,7 +37,6 @@ import * as Toggle from '#/components/forms/Toggle' import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' import {Loader} from '#/components/Loader' -import {PortalComponent} from '#/components/Portal' import {Text} from '#/components/Typography' export type PostInteractionSettingsFormProps = { @@ -55,15 +54,13 @@ export type PostInteractionSettingsFormProps = { export function PostInteractionSettingsControlledDialog({ control, - Portal, ...rest }: PostInteractionSettingsFormProps & { control: Dialog.DialogControlProps - Portal?: PortalComponent }) { const {_} = useLingui() return ( - <Dialog.Outer control={control} Portal={Portal}> + <Dialog.Outer control={control}> <Dialog.Handle /> <Dialog.ScrollableInner label={_(msg`Edit post interaction settings`)} @@ -207,7 +204,9 @@ export function PostInteractionSettingsDialogControlledInner( label={_(msg`Edit post interaction settings`)} style={[{maxWidth: 500}, a.w_full]}> {isLoading ? ( - <Loader size="xl" /> + <View style={[a.flex_1, a.py_4xl, a.align_center, a.justify_center]}> + <Loader size="xl" /> + </View> ) : ( <PostInteractionSettingsForm replySettingsDisabled={!isThreadgateOwnedByViewer} diff --git a/src/state/dialogs/index.tsx b/src/state/dialogs/index.tsx index 80893190f..f770e9c16 100644 --- a/src/state/dialogs/index.tsx +++ b/src/state/dialogs/index.tsx @@ -3,7 +3,7 @@ import React from 'react' import {isWeb} from '#/platform/detection' import {DialogControlRefProps} from '#/components/Dialog' import {Provider as GlobalDialogsProvider} from '#/components/dialogs/Context' -import {BottomSheet} from '../../../modules/bottom-sheet' +import {BottomSheetNativeComponent} from '../../../modules/bottom-sheet' interface IDialogContext { /** @@ -61,7 +61,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { return openDialogs.current.size > 0 } else { - BottomSheet.dismissAll() + BottomSheetNativeComponent.dismissAll() return false } }, []) diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index 8cc8fba0d..49a498cce 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -107,9 +107,9 @@ import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' import {EmojiArc_Stroke2_Corner0_Rounded as EmojiSmile} from '#/components/icons/Emoji' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' -import {createPortalGroup} from '#/components/Portal' import * as Prompt from '#/components/Prompt' import {Text as NewText} from '#/components/Typography' +import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet' import { composerReducer, createComposerState, @@ -117,8 +117,6 @@ import { } from './state/composer' import {NO_VIDEO, NoVideoState, processVideo, VideoState} from './state/video' -const Portal = createPortalGroup() - type CancelRef = { onPressCancel: () => void } @@ -522,7 +520,7 @@ export const ComposePost = ({ const keyboardVerticalOffset = useKeyboardVerticalOffset() return ( - <Portal.Provider> + <BottomSheetPortalProvider> <KeyboardAvoidingView testID="composePostView" behavior={isIOS ? 'padding' : 'height'} @@ -666,11 +664,7 @@ export const ComposePost = ({ /> </View> - <Gallery - images={images} - dispatch={dispatch} - Portal={Portal.Portal} - /> + <Gallery images={images} dispatch={dispatch} /> {extGif && ( <View style={a.relative} key={extGif.url}> @@ -684,7 +678,6 @@ export const ComposePost = ({ gif={extGif} altText={extGifAlt ?? ''} onSubmit={handleChangeGifAltText} - Portal={Portal.Portal} /> </View> )} @@ -744,7 +737,6 @@ export const ComposePost = ({ }, }) }} - Portal={Portal.Portal} /> </Animated.View> )} @@ -782,7 +774,6 @@ export const ComposePost = ({ }) }} style={bottomBarAnimatedStyle} - Portal={Portal.Portal} /> )} <View @@ -819,7 +810,6 @@ export const ComposePost = ({ onClose={focusTextInput} onSelectGif={onSelectGif} disabled={hasMedia} - Portal={Portal.Portal} /> {!isMobile ? ( <Button @@ -849,11 +839,9 @@ export const ComposePost = ({ onConfirm={onClose} confirmButtonCta={_(msg`Discard`)} confirmButtonColor="negative" - Portal={Portal.Portal} /> </KeyboardAvoidingView> - <Portal.Outlet /> - </Portal.Provider> + </BottomSheetPortalProvider> ) } diff --git a/src/view/com/composer/GifAltText.tsx b/src/view/com/composer/GifAltText.tsx index 01778c381..732bd4bd6 100644 --- a/src/view/com/composer/GifAltText.tsx +++ b/src/view/com/composer/GifAltText.tsx @@ -21,7 +21,6 @@ import * as TextField from '#/components/forms/TextField' import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' import {PlusSmall_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' -import {PortalComponent} from '#/components/Portal' import {Text} from '#/components/Typography' import {GifEmbed} from '../util/post-embeds/GifEmbed' import {AltTextReminder} from './photos/Gallery' @@ -30,12 +29,10 @@ export function GifAltTextDialog({ gif, altText, onSubmit, - Portal, }: { gif: Gif altText: string onSubmit: (alt: string) => void - Portal: PortalComponent }) { const {data} = useResolveGifQuery(gif) const vendorAltText = parseAltFromGIFDescription(data?.description ?? '').alt @@ -50,7 +47,6 @@ export function GifAltTextDialog({ thumb={data.thumb?.source.path} params={params} onSubmit={onSubmit} - Portal={Portal} /> ) } @@ -61,14 +57,12 @@ export function GifAltTextDialogLoaded({ onSubmit, params, thumb, - Portal, }: { vendorAltText: string altText: string onSubmit: (alt: string) => void params: EmbedPlayerParams thumb: string | undefined - Portal: PortalComponent }) { const control = Dialog.useDialogControl() const {_} = useLingui() @@ -113,8 +107,7 @@ export function GifAltTextDialogLoaded({ control={control} onClose={() => { onSubmit(altTextDraft) - }} - Portal={Portal}> + }}> <Dialog.Handle /> <AltTextInner vendorAltText={vendorAltText} diff --git a/src/view/com/composer/photos/Gallery.tsx b/src/view/com/composer/photos/Gallery.tsx index 3958a85c0..5ff7042bc 100644 --- a/src/view/com/composer/photos/Gallery.tsx +++ b/src/view/com/composer/photos/Gallery.tsx @@ -21,7 +21,6 @@ import {ComposerImage, cropImage} from '#/state/gallery' import {Text} from '#/view/com/util/text/Text' import {useTheme} from '#/alf' import * as Dialog from '#/components/Dialog' -import {PortalComponent} from '#/components/Portal' import {ComposerAction} from '../state/composer' import {EditImageDialog} from './EditImageDialog' import {ImageAltTextDialog} from './ImageAltTextDialog' @@ -31,7 +30,6 @@ const IMAGE_GAP = 8 interface GalleryProps { images: ComposerImage[] dispatch: (action: ComposerAction) => void - Portal: PortalComponent } export let Gallery = (props: GalleryProps): React.ReactNode => { @@ -59,12 +57,7 @@ interface GalleryInnerProps extends GalleryProps { containerInfo: Dimensions } -const GalleryInner = ({ - images, - containerInfo, - dispatch, - Portal, -}: GalleryInnerProps) => { +const GalleryInner = ({images, containerInfo, dispatch}: GalleryInnerProps) => { const {isMobile} = useWebMediaQueries() const {altTextControlStyle, imageControlsStyle, imageStyle} = @@ -118,7 +111,6 @@ const GalleryInner = ({ onRemove={() => { dispatch({type: 'embed_remove_image', image}) }} - Portal={Portal} /> ) })} @@ -135,7 +127,6 @@ type GalleryItemProps = { imageStyle?: ViewStyle onChange: (next: ComposerImage) => void onRemove: () => void - Portal: PortalComponent } const GalleryItem = ({ @@ -145,7 +136,6 @@ const GalleryItem = ({ imageStyle, onChange, onRemove, - Portal, }: GalleryItemProps): React.ReactNode => { const {_} = useLingui() const t = useTheme() @@ -240,7 +230,6 @@ const GalleryItem = ({ control={altTextControl} image={image} onChange={onChange} - Portal={Portal} /> <EditImageDialog diff --git a/src/view/com/composer/photos/ImageAltTextDialog.tsx b/src/view/com/composer/photos/ImageAltTextDialog.tsx index e9e8d4222..aa0b0987a 100644 --- a/src/view/com/composer/photos/ImageAltTextDialog.tsx +++ b/src/view/com/composer/photos/ImageAltTextDialog.tsx @@ -15,21 +15,18 @@ import * as Dialog from '#/components/Dialog' import {DialogControlProps} from '#/components/Dialog' import * as TextField from '#/components/forms/TextField' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' -import {PortalComponent} from '#/components/Portal' import {Text} from '#/components/Typography' type Props = { control: Dialog.DialogOuterProps['control'] image: ComposerImage onChange: (next: ComposerImage) => void - Portal: PortalComponent } export const ImageAltTextDialog = ({ control, image, onChange, - Portal, }: Props): React.ReactNode => { const [altText, setAltText] = React.useState(image.alt) @@ -41,8 +38,7 @@ export const ImageAltTextDialog = ({ ...image, alt: enforceLen(altText, MAX_ALT_TEXT, true), }) - }} - Portal={Portal}> + }}> <Dialog.Handle /> <ImageAltTextInner control={control} diff --git a/src/view/com/composer/photos/SelectGifBtn.tsx b/src/view/com/composer/photos/SelectGifBtn.tsx index d482e0783..d13df0a11 100644 --- a/src/view/com/composer/photos/SelectGifBtn.tsx +++ b/src/view/com/composer/photos/SelectGifBtn.tsx @@ -9,16 +9,14 @@ import {atoms as a, useTheme} from '#/alf' import {Button} from '#/components/Button' import {GifSelectDialog} from '#/components/dialogs/GifSelect' import {GifSquare_Stroke2_Corner0_Rounded as GifIcon} from '#/components/icons/Gif' -import {PortalComponent} from '#/components/Portal' type Props = { onClose: () => void onSelectGif: (gif: Gif) => void disabled?: boolean - Portal?: PortalComponent } -export function SelectGifBtn({onClose, onSelectGif, disabled, Portal}: Props) { +export function SelectGifBtn({onClose, onSelectGif, disabled}: Props) { const {_} = useLingui() const ref = useRef<{open: () => void}>(null) const t = useTheme() @@ -48,7 +46,6 @@ export function SelectGifBtn({onClose, onSelectGif, disabled, Portal}: Props) { controlRef={ref} onClose={onClose} onSelectGif={onSelectGif} - Portal={Portal} /> </> ) diff --git a/src/view/com/composer/threadgate/ThreadgateBtn.tsx b/src/view/com/composer/threadgate/ThreadgateBtn.tsx index 7e57a57d4..b0806180c 100644 --- a/src/view/com/composer/threadgate/ThreadgateBtn.tsx +++ b/src/view/com/composer/threadgate/ThreadgateBtn.tsx @@ -13,7 +13,6 @@ import * as Dialog from '#/components/Dialog' import {PostInteractionSettingsControlledDialog} from '#/components/dialogs/PostInteractionSettingsDialog' import {Earth_Stroke2_Corner0_Rounded as Earth} from '#/components/icons/Globe' import {Group3_Stroke2_Corner0_Rounded as Group} from '#/components/icons/Group' -import {PortalComponent} from '#/components/Portal' export function ThreadgateBtn({ postgate, @@ -21,7 +20,6 @@ export function ThreadgateBtn({ threadgateAllowUISettings, onChangeThreadgateAllowUISettings, style, - Portal, }: { postgate: AppBskyFeedPostgate.Record onChangePostgate: (v: AppBskyFeedPostgate.Record) => void @@ -30,8 +28,6 @@ export function ThreadgateBtn({ onChangeThreadgateAllowUISettings: (v: ThreadgateAllowUISetting[]) => void style?: StyleProp<AnimatedStyle<ViewStyle>> - - Portal: PortalComponent }) { const {_} = useLingui() const t = useTheme() @@ -81,7 +77,6 @@ export function ThreadgateBtn({ onChangePostgate={onChangePostgate} threadgateAllowUISettings={threadgateAllowUISettings} onChangeThreadgateAllowUISettings={onChangeThreadgateAllowUISettings} - Portal={Portal} /> </> ) diff --git a/src/view/com/composer/videos/SubtitleDialog.tsx b/src/view/com/composer/videos/SubtitleDialog.tsx index 04522ee1d..27c3de02b 100644 --- a/src/view/com/composer/videos/SubtitleDialog.tsx +++ b/src/view/com/composer/videos/SubtitleDialog.tsx @@ -17,7 +17,6 @@ import {CC_Stroke2_Corner0_Rounded as CCIcon} from '#/components/icons/CC' import {PageText_Stroke2_Corner0_Rounded as PageTextIcon} from '#/components/icons/PageText' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning' -import {PortalComponent} from '#/components/Portal' import {Text} from '#/components/Typography' import {SubtitleFilePicker} from './SubtitleFilePicker' @@ -30,7 +29,6 @@ interface Props { captions: CaptionsTrack[] saveAltText: (altText: string) => void setCaptions: (updater: (prev: CaptionsTrack[]) => CaptionsTrack[]) => void - Portal: PortalComponent } export function SubtitleDialogBtn(props: Props) { @@ -58,7 +56,7 @@ export function SubtitleDialogBtn(props: Props) { {isWeb ? <Trans>Captions & alt text</Trans> : <Trans>Alt text</Trans>} </ButtonText> </Button> - <Dialog.Outer control={control} Portal={props.Portal}> + <Dialog.Outer control={control}> <Dialog.Handle /> <SubtitleDialogInner {...props} /> </Dialog.Outer> diff --git a/src/view/screens/Storybook/Dialogs.tsx b/src/view/screens/Storybook/Dialogs.tsx index e6fcef555..343d7f07b 100644 --- a/src/view/screens/Storybook/Dialogs.tsx +++ b/src/view/screens/Storybook/Dialogs.tsx @@ -8,13 +8,10 @@ import {atoms as a} from '#/alf' import {Button, ButtonText} from '#/components/Button' import * as Dialog from '#/components/Dialog' import * as Menu from '#/components/Menu' -import {createPortalGroup} from '#/components/Portal' import * as Prompt from '#/components/Prompt' import {H3, P, Text} from '#/components/Typography' import {PlatformInfo} from '../../../../modules/expo-bluesky-swiss-army' -const Portal = createPortalGroup() - export function Dialogs() { const scrollable = Dialog.useDialogControl() const basic = Dialog.useDialogControl() @@ -201,41 +198,34 @@ export function Dialogs() { </Dialog.Outer> <Dialog.Outer control={withMenu}> - <Portal.Provider> - <Dialog.Inner label="test"> - <H3 nativeID="dialog-title">Dialog with Menu</H3> - <Menu.Root> - <Menu.Trigger label="Open menu"> - {({props}) => ( - <Button - style={a.mt_2xl} - label="Open menu" - color="primary" - variant="solid" - size="large" - {...props}> - <ButtonText>Open Menu</ButtonText> - </Button> - )} - </Menu.Trigger> - <Menu.Outer Portal={Portal.Portal}> - <Menu.Group> - <Menu.Item - label="Item 1" - onPress={() => console.log('item 1')}> - <Menu.ItemText>Item 1</Menu.ItemText> - </Menu.Item> - <Menu.Item - label="Item 2" - onPress={() => console.log('item 2')}> - <Menu.ItemText>Item 2</Menu.ItemText> - </Menu.Item> - </Menu.Group> - </Menu.Outer> - </Menu.Root> - </Dialog.Inner> - <Portal.Outlet /> - </Portal.Provider> + <Dialog.Inner label="test"> + <H3 nativeID="dialog-title">Dialog with Menu</H3> + <Menu.Root> + <Menu.Trigger label="Open menu"> + {({props}) => ( + <Button + style={a.mt_2xl} + label="Open menu" + color="primary" + variant="solid" + size="large" + {...props}> + <ButtonText>Open Menu</ButtonText> + </Button> + )} + </Menu.Trigger> + <Menu.Outer> + <Menu.Group> + <Menu.Item label="Item 1" onPress={() => console.log('item 1')}> + <Menu.ItemText>Item 1</Menu.ItemText> + </Menu.Item> + <Menu.Item label="Item 2" onPress={() => console.log('item 2')}> + <Menu.ItemText>Item 2</Menu.ItemText> + </Menu.Item> + </Menu.Group> + </Menu.Outer> + </Menu.Root> + </Dialog.Inner> </Dialog.Outer> <Dialog.Outer control={scrollable}> diff --git a/src/view/shell/index.tsx b/src/view/shell/index.tsx index 8bc3de24d..9f7569beb 100644 --- a/src/view/shell/index.tsx +++ b/src/view/shell/index.tsx @@ -34,6 +34,7 @@ import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' import {MutedWordsDialog} from '#/components/dialogs/MutedWords' import {SigninDialog} from '#/components/dialogs/Signin' import {Outlet as PortalOutlet} from '#/components/Portal' +import {BottomSheetOutlet} from '../../../modules/bottom-sheet' import {updateActiveViewAsync} from '../../../modules/expo-bluesky-swiss-army/src/VisibilityView' import {RoutesContainer, TabsNavigator} from '../../Navigation' import {Composer} from './Composer' @@ -119,6 +120,7 @@ function ShellInner() { <SigninDialog /> <Lightbox /> <PortalOutlet /> + <BottomSheetOutlet /> </> ) } |