Skip to content

Commit

Permalink
[馃惔] Option to share via chat in post dropdown (#4231)
Browse files Browse the repository at this point in the history
* add send via chat button to post dropdown

(cherry picked from commit d8458c0)

* let usePostQuery take uris with DIDs

(cherry picked from commit 16b577c)

* add embed preview in composer

(cherry picked from commit 795ceb9)

* rm log

(cherry picked from commit 374d6b8)

* remove params properly, or at least as close to

(cherry picked from commit c20e006)

* show images in preview

(cherry picked from commit 5bb617a)

* Register embed immediately

(cherry picked from commit ee120d5)

* Add hover to match embeds

(cherry picked from commit 5297a5b)

* Update post dropdown copy

(cherry picked from commit bc7e9f6)

* Embed preview style tweaks

(cherry picked from commit 9e3ccb0)

* use hydrated posts from API and just use postembed component

(cherry picked from commit cc0b84d)

* fix type error

(cherry picked from commit 9c49b94)

* undo needless export

(cherry picked from commit 1186701)

* fix overflow

(cherry picked from commit 8868d50)

---------

Co-authored-by: Eric Bailey <[email protected]>
  • Loading branch information
mozzius and estrattonbailey committed May 31, 2024
1 parent 22e1eb1 commit cd3b502
Show file tree
Hide file tree
Showing 21 changed files with 713 additions and 407 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"open-analyzer": "EXPO_PUBLIC_OPEN_ANALYZER=1 yarn build-web"
},
"dependencies": {
"@atproto/api": "^0.12.13",
"@atproto/api": "^0.12.14",
"@bam.tech/react-native-image-resizer": "^3.0.4",
"@braintree/sanitize-url": "^6.0.2",
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
Expand Down
2 changes: 1 addition & 1 deletion src/components/dms/MessageItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ let MessageItem = ({
return (
<View style={[isFromSelf ? a.mr_md : a.ml_md]}>
<ActionsWrapper isFromSelf={isFromSelf} message={message}>
{AppBskyEmbedRecord.isMain(message.embed) && (
{AppBskyEmbedRecord.isView(message.embed) && (
<MessageItemEmbed embed={message.embed} />
)}
{rt.text.length > 0 && (
Expand Down
99 changes: 6 additions & 93 deletions src/components/dms/MessageItemEmbed.tsx
Original file line number Diff line number Diff line change
@@ -1,108 +1,21 @@
import React, {useMemo} from 'react'
import React from 'react'
import {View} from 'react-native'
import {
AppBskyEmbedRecord,
AppBskyFeedPost,
AtUri,
RichText as RichTextAPI,
} from '@atproto/api'
import {AppBskyEmbedRecord} from '@atproto/api'

import {moderatePost_wrapped as moderatePost} from '#/lib/moderatePost_wrapped'
import {makeProfileLink} from '#/lib/routes/links'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {usePostQuery} from '#/state/queries/post'
import {PostEmbeds} from '#/view/com/util/post-embeds'
import {PostMeta} from '#/view/com/util/PostMeta'
import {atoms as a, useTheme} from '#/alf'
import {Link} from '#/components/Link'
import {ContentHider} from '#/components/moderation/ContentHider'
import {PostAlerts} from '#/components/moderation/PostAlerts'
import {RichText} from '#/components/RichText'

let MessageItemEmbed = ({
embed,
}: {
embed: AppBskyEmbedRecord.Main
embed: AppBskyEmbedRecord.View
}): React.ReactNode => {
const t = useTheme()
const {data: post} = usePostQuery(embed.record.uri)

const moderationOpts = useModerationOpts()
const moderation = useMemo(
() =>
moderationOpts && post ? moderatePost(post, moderationOpts) : undefined,
[moderationOpts, post],
)

const {rt, record} = useMemo(() => {
if (
post &&
AppBskyFeedPost.isRecord(post.record) &&
AppBskyFeedPost.validateRecord(post.record).success
) {
return {
rt: new RichTextAPI({
text: post.record.text,
facets: post.record.facets,
}),
record: post.record,
}
}

return {rt: undefined, record: undefined}
}, [post])

if (!post || !moderation || !rt || !record) {
return null
}

const itemUrip = new AtUri(post.uri)
const itemHref = makeProfileLink(post.author, 'post', itemUrip.rkey)

return (
<Link to={itemHref}>
<View
style={[
a.w_full,
t.atoms.bg,
t.atoms.border_contrast_low,
a.rounded_md,
a.border,
a.p_md,
a.my_xs,
]}>
<PostMeta
showAvatar
author={post.author}
moderation={moderation}
authorHasWarning={!!post.author.labels?.length}
timestamp={post.indexedAt}
postHref={itemHref}
/>
<ContentHider modui={moderation.ui('contentView')}>
<PostAlerts modui={moderation.ui('contentView')} style={a.py_xs} />
{rt.text && (
<View style={a.mt_xs}>
<RichText
enableTags
testID="postText"
value={rt}
style={[a.text_sm, t.atoms.text_contrast_high]}
authorHandle={post.author.handle}
/>
</View>
)}
{post.embed && (
<PostEmbeds
embed={post.embed}
moderation={moderation}
style={a.mt_xs}
quoteTextStyle={[a.text_sm, t.atoms.text_contrast_high]}
/>
)}
</ContentHider>
</View>
</Link>
<View style={[a.my_xs, t.atoms.bg, a.rounded_md, {flexBasis: 0}]}>
<PostEmbeds embed={embed} />
</View>
)
}
MessageItemEmbed = React.memo(MessageItemEmbed)
Expand Down
67 changes: 67 additions & 0 deletions src/components/dms/dialogs/NewChatDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, {useCallback} from 'react'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'

import {useGetConvoForMembers} from '#/state/queries/messages/get-convo-for-members'
import {logEvent} from 'lib/statsig/statsig'
import {FAB} from '#/view/com/util/fab/FAB'
import * as Toast from '#/view/com/util/Toast'
import {useTheme} from '#/alf'
import * as Dialog from '#/components/Dialog'
import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
import {SearchablePeopleList} from './SearchablePeopleList'

export function NewChat({
control,
onNewChat,
}: {
control: Dialog.DialogControlProps
onNewChat: (chatId: string) => void
}) {
const t = useTheme()
const {_} = useLingui()

const {mutate: createChat} = useGetConvoForMembers({
onSuccess: data => {
onNewChat(data.convo.id)

if (!data.convo.lastMessage) {
logEvent('chat:create', {logContext: 'NewChatDialog'})
}
logEvent('chat:open', {logContext: 'NewChatDialog'})
},
onError: error => {
Toast.show(error.message)
},
})

const onCreateChat = useCallback(
(did: string) => {
control.close(() => createChat([did]))
},
[control, createChat],
)

return (
<>
<FAB
testID="newChatFAB"
onPress={control.open}
icon={<Plus size="lg" fill={t.palette.white} />}
accessibilityRole="button"
accessibilityLabel={_(msg`New chat`)}
accessibilityHint=""
/>

<Dialog.Outer
control={control}
testID="newChatDialog"
nativeOptions={{sheet: {snapPoints: ['100%']}}}>
<SearchablePeopleList
title={_(msg`Start a new chat`)}
onSelectChat={onCreateChat}
/>
</Dialog.Outer>
</>
)
}
Loading

0 comments on commit cd3b502

Please sign in to comment.