Update composer to new attachment style
This commit is contained in:
@@ -145,8 +145,6 @@ export function MessageComposer({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ComposerContainer>
|
<ComposerContainer>
|
||||||
{children}
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
collapsable={false}
|
collapsable={false}
|
||||||
ref={native(
|
ref={native(
|
||||||
@@ -162,6 +160,8 @@ export function MessageComposer({
|
|||||||
style={[a.flex_1, a.rounded_xl, {minHeight: MIN_HEIGHT}]}
|
style={[a.flex_1, a.rounded_xl, {minHeight: MIN_HEIGHT}]}
|
||||||
tintColor={t.palette.contrast_50}
|
tintColor={t.palette.contrast_50}
|
||||||
fallbackStyle={[t.atoms.bg_contrast_50]}>
|
fallbackStyle={[t.atoms.bg_contrast_50]}>
|
||||||
|
{children}
|
||||||
|
<View style={[a.flex_1]}>
|
||||||
{IS_WEB && (
|
{IS_WEB && (
|
||||||
<EmojiPicker.Root
|
<EmojiPicker.Root
|
||||||
onEmojiSelect={emoji =>
|
onEmojiSelect={emoji =>
|
||||||
@@ -236,6 +236,7 @@ export function MessageComposer({
|
|||||||
handleSubmit()
|
handleSubmit()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</View>
|
||||||
</GlassView>
|
</GlassView>
|
||||||
<SubmitButton onPress={handleSubmit} disabled={submitDisabled} />
|
<SubmitButton onPress={handleSubmit} disabled={submitDisabled} />
|
||||||
</GlassContainer>
|
</GlassContainer>
|
||||||
|
|||||||
@@ -158,7 +158,6 @@ export function MessageInput({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ComposerContainer>
|
<ComposerContainer>
|
||||||
{children}
|
|
||||||
<GlassContainer
|
<GlassContainer
|
||||||
style={[a.flex_row, a.align_end, a.gap_sm]}
|
style={[a.flex_row, a.align_end, a.gap_sm]}
|
||||||
spacing={tokens.space.xs}>
|
spacing={tokens.space.xs}>
|
||||||
@@ -168,6 +167,7 @@ export function MessageInput({
|
|||||||
style={[a.flex_1, a.rounded_xl, {minHeight: MIN_HEIGHT}]}
|
style={[a.flex_1, a.rounded_xl, {minHeight: MIN_HEIGHT}]}
|
||||||
tintColor={t.palette.contrast_50}
|
tintColor={t.palette.contrast_50}
|
||||||
fallbackStyle={[t.atoms.bg_contrast_50]}>
|
fallbackStyle={[t.atoms.bg_contrast_50]}>
|
||||||
|
{children}
|
||||||
<AnimatedTextInput
|
<AnimatedTextInput
|
||||||
nativeID={textInputId}
|
nativeID={textInputId}
|
||||||
accessibilityLabel={l`Message input field`}
|
accessibilityLabel={l`Message input field`}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import {
|
|||||||
moderatePost,
|
moderatePost,
|
||||||
RichText as RichTextAPI,
|
RichText as RichTextAPI,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {type RouteProp, useNavigation, useRoute} from '@react-navigation/native'
|
import {type RouteProp, useNavigation, useRoute} from '@react-navigation/native'
|
||||||
|
|
||||||
|
import {HITSLOP_20} from '#/lib/constants'
|
||||||
import {makeProfileLink} from '#/lib/routes/links'
|
import {makeProfileLink} from '#/lib/routes/links'
|
||||||
import {
|
import {
|
||||||
type CommonNavigatorParams,
|
type CommonNavigatorParams,
|
||||||
@@ -25,8 +25,8 @@ import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
|||||||
import {usePostQuery} from '#/state/queries/post'
|
import {usePostQuery} from '#/state/queries/post'
|
||||||
import {PostMeta} from '#/view/com/util/PostMeta'
|
import {PostMeta} from '#/view/com/util/PostMeta'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Button, ButtonIcon} from '#/components/Button'
|
import {Button} from '#/components/Button'
|
||||||
import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
|
import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import * as MediaPreview from '#/components/MediaPreview'
|
import * as MediaPreview from '#/components/MediaPreview'
|
||||||
import {ContentHider} from '#/components/moderation/ContentHider'
|
import {ContentHider} from '#/components/moderation/ContentHider'
|
||||||
@@ -41,10 +41,10 @@ export function useMessageEmbed() {
|
|||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const embedFromParams = route.params.embed
|
const embedFromParams = route.params.embed
|
||||||
|
|
||||||
const [embedUri, setEmbed] = useState(embedFromParams)
|
const [embedUri, setEmbedUri] = useState(embedFromParams)
|
||||||
|
|
||||||
if (embedFromParams && embedUri !== embedFromParams) {
|
if (embedFromParams && embedUri !== embedFromParams) {
|
||||||
setEmbed(embedFromParams)
|
setEmbedUri(embedFromParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -53,7 +53,7 @@ export function useMessageEmbed() {
|
|||||||
(embedUrl: string | undefined) => {
|
(embedUrl: string | undefined) => {
|
||||||
if (!embedUrl) {
|
if (!embedUrl) {
|
||||||
navigation.setParams({embed: ''})
|
navigation.setParams({embed: ''})
|
||||||
setEmbed(undefined)
|
setEmbedUri(undefined)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ export function useMessageEmbed() {
|
|||||||
const [_0, user, _1, rkey] = url.split('/').filter(Boolean)
|
const [_0, user, _1, rkey] = url.split('/').filter(Boolean)
|
||||||
const uri = makeRecordUri(user, 'app.bsky.feed.post', rkey)
|
const uri = makeRecordUri(user, 'app.bsky.feed.post', rkey)
|
||||||
|
|
||||||
setEmbed(uri)
|
setEmbedUri(uri)
|
||||||
},
|
},
|
||||||
[embedFromParams, navigation],
|
[embedFromParams, navigation],
|
||||||
),
|
),
|
||||||
@@ -103,7 +103,7 @@ export function MessageInputEmbed({
|
|||||||
setEmbed: (embedUrl: string | undefined) => void
|
setEmbed: (embedUrl: string | undefined) => void
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
|
|
||||||
const {data: post, status} = usePostQuery(embedUri)
|
const {data: post, status} = usePostQuery(embedUri)
|
||||||
|
|
||||||
@@ -138,25 +138,30 @@ export function MessageInputEmbed({
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = null
|
const onRemove = () => {
|
||||||
|
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
|
||||||
|
setEmbed(undefined)
|
||||||
|
}
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 'pending':
|
// case 'success':
|
||||||
content = (
|
case 'pending': {
|
||||||
<View
|
return (
|
||||||
style={[a.flex_1, {minHeight: 64}, a.justify_center, a.align_center]}>
|
<SimpleContainer onRemove={onRemove}>
|
||||||
<Loader />
|
<Loader />
|
||||||
</View>
|
</SimpleContainer>
|
||||||
)
|
)
|
||||||
break
|
}
|
||||||
case 'error':
|
case 'error': {
|
||||||
content = (
|
return (
|
||||||
<View
|
<SimpleContainer onRemove={onRemove}>
|
||||||
style={[a.flex_1, {minHeight: 64}, a.justify_center, a.align_center]}>
|
<Text style={[a.text_center, t.atoms.text_contrast_medium, a.italic]}>
|
||||||
<Text style={a.text_center}>Could not fetch post</Text>
|
<Trans>Could not fetch post</Trans>
|
||||||
</View>
|
</Text>
|
||||||
|
</SimpleContainer>
|
||||||
)
|
)
|
||||||
break
|
}
|
||||||
case 'success':
|
case 'success': {
|
||||||
const itemUrip = new AtUri(post.uri)
|
const itemUrip = new AtUri(post.uri)
|
||||||
const itemHref = makeProfileLink(post.author, 'post', itemUrip.rkey)
|
const itemHref = makeProfileLink(post.author, 'post', itemUrip.rkey)
|
||||||
|
|
||||||
@@ -164,30 +169,41 @@ export function MessageInputEmbed({
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
content = (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.flex_1,
|
a.flex_1,
|
||||||
t.atoms.bg,
|
t.atoms.border_contrast_high,
|
||||||
t.atoms.border_contrast_low,
|
|
||||||
a.rounded_md,
|
a.rounded_md,
|
||||||
a.border,
|
a.border,
|
||||||
a.p_sm,
|
a.p_sm,
|
||||||
a.mb_sm,
|
a.mt_sm,
|
||||||
]}
|
a.mx_sm,
|
||||||
pointerEvents="none">
|
]}>
|
||||||
|
<View style={[a.flex_1, a.flex_row, a.gap_sm]}>
|
||||||
<PostMeta
|
<PostMeta
|
||||||
showAvatar
|
showAvatar
|
||||||
author={post.author}
|
author={post.author}
|
||||||
moderation={moderation}
|
moderation={moderation}
|
||||||
timestamp={post.indexedAt}
|
timestamp={post.indexedAt}
|
||||||
postHref={itemHref}
|
postHref={itemHref}
|
||||||
style={a.flex_0}
|
linkDisabled
|
||||||
/>
|
/>
|
||||||
|
<Button
|
||||||
|
label={l`Remove embed`}
|
||||||
|
onPress={onRemove}
|
||||||
|
style={[a.px_2xs, {transform: [{translateY: -2}]}]}
|
||||||
|
hitSlop={HITSLOP_20}>
|
||||||
|
<XIcon size="xs" style={t.atoms.text_contrast_high} />
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
<ContentHider modui={moderation.ui('contentView')}>
|
<ContentHider modui={moderation.ui('contentView')}>
|
||||||
<PostAlerts modui={moderation.ui('contentView')} style={a.py_xs} />
|
<PostAlerts
|
||||||
|
modui={moderation.ui('contentView')}
|
||||||
|
style={a.py_xs}
|
||||||
|
size="sm"
|
||||||
|
/>
|
||||||
{rt.text && (
|
{rt.text && (
|
||||||
<View style={a.mt_xs}>
|
|
||||||
<RichText
|
<RichText
|
||||||
enableTags
|
enableTags
|
||||||
testID="postText"
|
testID="postText"
|
||||||
@@ -196,30 +212,52 @@ export function MessageInputEmbed({
|
|||||||
authorHandle={post.author.handle}
|
authorHandle={post.author.handle}
|
||||||
numberOfLines={3}
|
numberOfLines={3}
|
||||||
/>
|
/>
|
||||||
</View>
|
|
||||||
)}
|
)}
|
||||||
<MediaPreview.Embed embed={post.embed} style={a.mt_sm} />
|
<MediaPreview.Embed embed={post.embed} style={a.mt_sm} />
|
||||||
</ContentHider>
|
</ContentHider>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function SimpleContainer({
|
||||||
|
children,
|
||||||
|
onRemove,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode
|
||||||
|
onRemove?: () => void
|
||||||
|
}) {
|
||||||
|
const t = useTheme()
|
||||||
|
const {t: l} = useLingui()
|
||||||
return (
|
return (
|
||||||
<View style={[a.flex_row, a.gap_sm]}>
|
<View
|
||||||
{content}
|
style={[
|
||||||
|
a.flex_1,
|
||||||
|
{minHeight: 80},
|
||||||
|
a.justify_center,
|
||||||
|
a.align_center,
|
||||||
|
t.atoms.border_contrast_high,
|
||||||
|
a.rounded_md,
|
||||||
|
a.border,
|
||||||
|
a.mt_sm,
|
||||||
|
a.mx_sm,
|
||||||
|
]}>
|
||||||
|
{children}
|
||||||
|
{onRemove && (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Remove embed`)}
|
label={l`Remove embed`}
|
||||||
onPress={() => {
|
onPress={onRemove}
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
|
style={[
|
||||||
setEmbed(undefined)
|
a.absolute,
|
||||||
}}
|
{top: 10, right: 8},
|
||||||
size="tiny"
|
a.px_2xs,
|
||||||
variant="solid"
|
{transform: [{translateY: -2}]},
|
||||||
color="secondary"
|
]}
|
||||||
shape="round">
|
hitSlop={HITSLOP_20}>
|
||||||
<ButtonIcon icon={X} />
|
<XIcon size="xs" style={t.atoms.text_contrast_high} />
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user