support portals, minor refactor
This commit is contained in:
@@ -37,7 +37,7 @@ export function GifSelectDialog({
|
|||||||
onSelectGif: onSelectGifProp,
|
onSelectGif: onSelectGifProp,
|
||||||
}: {
|
}: {
|
||||||
controlRef: React.RefObject<{open: () => void}>
|
controlRef: React.RefObject<{open: () => void}>
|
||||||
onClose: () => void
|
onClose?: () => void
|
||||||
onSelectGif: (gif: Gif) => void
|
onSelectGif: (gif: Gif) => void
|
||||||
}) {
|
}) {
|
||||||
const control = Dialog.useDialogControl()
|
const control = Dialog.useDialogControl()
|
||||||
|
|||||||
@@ -497,10 +497,6 @@ export const ComposePost = ({
|
|||||||
openEmojiPicker?.(textInput.current?.getCursorPosition())
|
openEmojiPicker?.(textInput.current?.getCursorPosition())
|
||||||
}, [openEmojiPicker])
|
}, [openEmojiPicker])
|
||||||
|
|
||||||
const focusTextInput = useCallback(() => {
|
|
||||||
textInput.current?.focus()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const onSelectGif = useCallback((gif: Gif) => {
|
const onSelectGif = useCallback((gif: Gif) => {
|
||||||
dispatch({type: 'embed_add_gif', gif})
|
dispatch({type: 'embed_add_gif', gif})
|
||||||
}, [])
|
}, [])
|
||||||
@@ -569,6 +565,7 @@ export const ComposePost = ({
|
|||||||
dispatch({type: 'update_labels', labels: nextLabels})
|
dispatch({type: 'update_labels', labels: nextLabels})
|
||||||
}}
|
}}
|
||||||
hasMedia={hasMedia || Boolean(extLink)}
|
hasMedia={hasMedia || Boolean(extLink)}
|
||||||
|
Portal={Portal.Portal}
|
||||||
/>
|
/>
|
||||||
{canPost ? (
|
{canPost ? (
|
||||||
<Button
|
<Button
|
||||||
@@ -807,7 +804,6 @@ export const ComposePost = ({
|
|||||||
onAdd={onImageAdd}
|
onAdd={onImageAdd}
|
||||||
/>
|
/>
|
||||||
<SelectGifBtn
|
<SelectGifBtn
|
||||||
onClose={focusTextInput}
|
|
||||||
onSelectGif={onSelectGif}
|
onSelectGif={onSelectGif}
|
||||||
disabled={hasMedia}
|
disabled={hasMedia}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import {msg, Trans} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {ShieldExclamation} from '#/lib/icons'
|
import {ShieldExclamation} from '#/lib/icons'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import * as ToggleButton from '#/components/forms/ToggleButton'
|
import * as ToggleButton from '#/components/forms/ToggleButton'
|
||||||
import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
|
import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
|
||||||
|
import {PortalComponent} from '#/components/Portal'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
const ADULT_CONTENT_LABELS = ['sexual', 'nudity', 'porn']
|
const ADULT_CONTENT_LABELS = ['sexual', 'nudity', 'porn']
|
||||||
@@ -18,10 +18,12 @@ export function LabelsBtn({
|
|||||||
labels,
|
labels,
|
||||||
hasMedia,
|
hasMedia,
|
||||||
onChange,
|
onChange,
|
||||||
|
Portal,
|
||||||
}: {
|
}: {
|
||||||
labels: string[]
|
labels: string[]
|
||||||
hasMedia: boolean
|
hasMedia: boolean
|
||||||
onChange: (v: string[]) => void
|
onChange: (v: string[]) => void
|
||||||
|
Portal: PortalComponent
|
||||||
}) {
|
}) {
|
||||||
const control = Dialog.useDialogControl()
|
const control = Dialog.useDialogControl()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
@@ -52,9 +54,7 @@ export function LabelsBtn({
|
|||||||
msg`Opens a dialog to add a content warning to your post`,
|
msg`Opens a dialog to add a content warning to your post`,
|
||||||
)}
|
)}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (isNative && Keyboard.isVisible()) {
|
Keyboard.dismiss()
|
||||||
Keyboard.dismiss()
|
|
||||||
}
|
|
||||||
control.open()
|
control.open()
|
||||||
}}>
|
}}>
|
||||||
<ShieldExclamation style={{color: t.palette.primary_500}} size={24} />
|
<ShieldExclamation style={{color: t.palette.primary_500}} size={24} />
|
||||||
@@ -63,122 +63,143 @@ export function LabelsBtn({
|
|||||||
) : null}
|
) : null}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Dialog.Outer control={control}>
|
<Dialog.Outer
|
||||||
|
control={control}
|
||||||
|
Portal={Portal}
|
||||||
|
nativeOptions={{preventExpansion: true}}>
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
<Dialog.ScrollableInner
|
<DialogInner
|
||||||
label={_(msg`Add a content warning`)}
|
labels={labels}
|
||||||
style={[{maxWidth: 500}, a.w_full]}>
|
onChange={onChange}
|
||||||
<View style={[a.flex_1, a.gap_md]}>
|
hasAdultSelection={hasAdultSelection}
|
||||||
<Text style={[a.text_2xl, a.font_bold]}>
|
hasMedia={hasMedia}
|
||||||
<Trans>Add a content warning</Trans>
|
removeAdultLabel={removeAdultLabel}
|
||||||
</Text>
|
/>
|
||||||
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.border,
|
|
||||||
a.p_md,
|
|
||||||
t.atoms.border_contrast_high,
|
|
||||||
a.rounded_md,
|
|
||||||
]}>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.justify_between,
|
|
||||||
a.pb_sm,
|
|
||||||
]}>
|
|
||||||
<Text style={[a.font_bold, a.text_lg]}>
|
|
||||||
<Trans>Adult Content</Trans>
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
label={_(msg`Remove`)}
|
|
||||||
variant="ghost"
|
|
||||||
color="primary"
|
|
||||||
size="xsmall"
|
|
||||||
onPress={removeAdultLabel}
|
|
||||||
disabled={!hasAdultSelection}
|
|
||||||
style={{opacity: hasAdultSelection ? 1 : 0}}
|
|
||||||
aria-hidden={!hasAdultSelection}>
|
|
||||||
<ButtonText>
|
|
||||||
<Trans>Remove</Trans>
|
|
||||||
</ButtonText>
|
|
||||||
</Button>
|
|
||||||
</View>
|
|
||||||
{hasMedia ? (
|
|
||||||
<>
|
|
||||||
<ToggleButton.Group
|
|
||||||
label={_(msg`Adult Content labels`)}
|
|
||||||
values={labels}
|
|
||||||
onChange={values => {
|
|
||||||
onChange(values)
|
|
||||||
LayoutAnimation.configureNext(
|
|
||||||
LayoutAnimation.Presets.easeInEaseOut,
|
|
||||||
)
|
|
||||||
}}>
|
|
||||||
<ToggleButton.Button
|
|
||||||
name="sexual"
|
|
||||||
label={_(msg`Suggestive`)}>
|
|
||||||
<ToggleButton.ButtonText>
|
|
||||||
<Trans>Suggestive</Trans>
|
|
||||||
</ToggleButton.ButtonText>
|
|
||||||
</ToggleButton.Button>
|
|
||||||
<ToggleButton.Button name="nudity" label={_(msg`Nudity`)}>
|
|
||||||
<ToggleButton.ButtonText>
|
|
||||||
<Trans>Nudity</Trans>
|
|
||||||
</ToggleButton.ButtonText>
|
|
||||||
</ToggleButton.Button>
|
|
||||||
<ToggleButton.Button name="porn" label={_(msg`Porn`)}>
|
|
||||||
<ToggleButton.ButtonText>
|
|
||||||
<Trans>Porn</Trans>
|
|
||||||
</ToggleButton.ButtonText>
|
|
||||||
</ToggleButton.Button>
|
|
||||||
</ToggleButton.Group>
|
|
||||||
|
|
||||||
<Text style={[a.mt_sm, t.atoms.text_contrast_medium]}>
|
|
||||||
{labels.includes('sexual') ? (
|
|
||||||
<Trans>Pictures meant for adults.</Trans>
|
|
||||||
) : labels.includes('nudity') ? (
|
|
||||||
<Trans>Artistic or non-erotic nudity.</Trans>
|
|
||||||
) : labels.includes('porn') ? (
|
|
||||||
<Trans>Sexual activity or erotic nudity.</Trans>
|
|
||||||
) : (
|
|
||||||
<Trans>
|
|
||||||
If none are selected, suitable for all ages.
|
|
||||||
</Trans>
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<View>
|
|
||||||
<Text style={t.atoms.text_contrast_medium}>
|
|
||||||
<Trans>
|
|
||||||
<Text style={[a.font_bold, t.atoms.text_contrast_medium]}>
|
|
||||||
Not Applicable.
|
|
||||||
</Text>{' '}
|
|
||||||
This warning is only available for posts with media
|
|
||||||
attached.
|
|
||||||
</Trans>
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
label={_(msg`Done`)}
|
|
||||||
onPress={() => control.close()}
|
|
||||||
onAccessibilityEscape={control.close}
|
|
||||||
color="primary"
|
|
||||||
size="medium"
|
|
||||||
variant="solid"
|
|
||||||
style={a.mt_xl}>
|
|
||||||
<ButtonText>
|
|
||||||
<Trans>Done</Trans>
|
|
||||||
</ButtonText>
|
|
||||||
</Button>
|
|
||||||
</Dialog.ScrollableInner>
|
|
||||||
</Dialog.Outer>
|
</Dialog.Outer>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function DialogInner({
|
||||||
|
labels,
|
||||||
|
onChange,
|
||||||
|
hasAdultSelection,
|
||||||
|
hasMedia,
|
||||||
|
removeAdultLabel,
|
||||||
|
}: {
|
||||||
|
labels: string[]
|
||||||
|
onChange: (v: string[]) => void
|
||||||
|
hasAdultSelection: boolean
|
||||||
|
hasMedia: boolean
|
||||||
|
removeAdultLabel: () => void
|
||||||
|
}) {
|
||||||
|
const {_} = useLingui()
|
||||||
|
const control = Dialog.useDialogContext()
|
||||||
|
const t = useTheme()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog.ScrollableInner
|
||||||
|
label={_(msg`Add a content warning`)}
|
||||||
|
style={[{maxWidth: 500}, a.w_full]}>
|
||||||
|
<View style={[a.flex_1, a.gap_md]}>
|
||||||
|
<Text style={[a.text_2xl, a.font_bold]}>
|
||||||
|
<Trans>Add a content warning</Trans>
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.border,
|
||||||
|
a.p_md,
|
||||||
|
t.atoms.border_contrast_high,
|
||||||
|
a.rounded_md,
|
||||||
|
]}>
|
||||||
|
<View
|
||||||
|
style={[a.flex_row, a.align_center, a.justify_between, a.pb_sm]}>
|
||||||
|
<Text style={[a.font_bold, a.text_lg]}>
|
||||||
|
<Trans>Adult Content</Trans>
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
label={_(msg`Remove`)}
|
||||||
|
variant="ghost"
|
||||||
|
color="primary"
|
||||||
|
size="tiny"
|
||||||
|
onPress={removeAdultLabel}
|
||||||
|
disabled={!hasAdultSelection}
|
||||||
|
style={{opacity: hasAdultSelection ? 1 : 0}}
|
||||||
|
aria-hidden={!hasAdultSelection}>
|
||||||
|
<ButtonText>
|
||||||
|
<Trans>Remove</Trans>
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
{hasMedia ? (
|
||||||
|
<>
|
||||||
|
<ToggleButton.Group
|
||||||
|
label={_(msg`Adult Content labels`)}
|
||||||
|
values={labels}
|
||||||
|
onChange={values => {
|
||||||
|
onChange(values)
|
||||||
|
LayoutAnimation.configureNext(
|
||||||
|
LayoutAnimation.Presets.easeInEaseOut,
|
||||||
|
)
|
||||||
|
}}>
|
||||||
|
<ToggleButton.Button name="sexual" label={_(msg`Suggestive`)}>
|
||||||
|
<ToggleButton.ButtonText>
|
||||||
|
<Trans>Suggestive</Trans>
|
||||||
|
</ToggleButton.ButtonText>
|
||||||
|
</ToggleButton.Button>
|
||||||
|
<ToggleButton.Button name="nudity" label={_(msg`Nudity`)}>
|
||||||
|
<ToggleButton.ButtonText>
|
||||||
|
<Trans>Nudity</Trans>
|
||||||
|
</ToggleButton.ButtonText>
|
||||||
|
</ToggleButton.Button>
|
||||||
|
<ToggleButton.Button name="porn" label={_(msg`Porn`)}>
|
||||||
|
<ToggleButton.ButtonText>
|
||||||
|
<Trans>Porn</Trans>
|
||||||
|
</ToggleButton.ButtonText>
|
||||||
|
</ToggleButton.Button>
|
||||||
|
</ToggleButton.Group>
|
||||||
|
|
||||||
|
<Text style={[a.mt_sm, t.atoms.text_contrast_medium]}>
|
||||||
|
{labels.includes('sexual') ? (
|
||||||
|
<Trans>Pictures meant for adults.</Trans>
|
||||||
|
) : labels.includes('nudity') ? (
|
||||||
|
<Trans>Artistic or non-erotic nudity.</Trans>
|
||||||
|
) : labels.includes('porn') ? (
|
||||||
|
<Trans>Sexual activity or erotic nudity.</Trans>
|
||||||
|
) : (
|
||||||
|
<Trans>If none are selected, suitable for all ages.</Trans>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<View>
|
||||||
|
<Text style={t.atoms.text_contrast_medium}>
|
||||||
|
<Trans>
|
||||||
|
<Text style={[a.font_bold, t.atoms.text_contrast_medium]}>
|
||||||
|
Not Applicable.
|
||||||
|
</Text>{' '}
|
||||||
|
This warning is only available for posts with media attached.
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
label={_(msg`Done`)}
|
||||||
|
onPress={() => control.close()}
|
||||||
|
onAccessibilityEscape={() => control.close()}
|
||||||
|
color="primary"
|
||||||
|
size="large"
|
||||||
|
variant="solid"
|
||||||
|
style={a.mt_xl}>
|
||||||
|
<ButtonText>
|
||||||
|
<Trans>Done</Trans>
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
|
</Dialog.ScrollableInner>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {GifSelectDialog} from '#/components/dialogs/GifSelect'
|
|||||||
import {GifSquare_Stroke2_Corner0_Rounded as GifIcon} from '#/components/icons/Gif'
|
import {GifSquare_Stroke2_Corner0_Rounded as GifIcon} from '#/components/icons/Gif'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClose: () => void
|
onClose?: () => void
|
||||||
onSelectGif: (gif: Gif) => void
|
onSelectGif: (gif: Gif) => void
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user