This commit is contained in:
Samuel Newman
2025-10-21 17:09:01 +03:00
parent 55d022ace9
commit bda67ed24e
3 changed files with 108 additions and 130 deletions
+108 -127
View File
@@ -30,16 +30,14 @@ import {
import {precacheProfile} from '#/state/queries/profile' import {precacheProfile} from '#/state/queries/profile'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {TimeElapsed} from '#/view/com/util/TimeElapsed' import {TimeElapsed} from '#/view/com/util/TimeElapsed'
import {PreviewableUserAvatar, UserAvatar} from '#/view/com/util/UserAvatar' import {UserAvatar} from '#/view/com/util/UserAvatar'
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf' import {atoms as a, useTheme, web} from '#/alf'
import * as tokens from '#/alf/tokens' import * as tokens from '#/alf/tokens'
import {Button} from '#/components/Button'
import {useDialogControl} from '#/components/Dialog' import {useDialogControl} from '#/components/Dialog'
import {ConvoMenu} from '#/components/dms/ConvoMenu'
import {LeaveConvoPrompt} from '#/components/dms/LeaveConvoPrompt'
import {Bell2Off_Filled_Corner0_Rounded as BellStroke} from '#/components/icons/Bell2' import {Bell2Off_Filled_Corner0_Rounded as BellStroke} from '#/components/icons/Bell2'
import {Envelope_Open_Stroke2_Corner0_Rounded as EnvelopeOpen} from '#/components/icons/EnveopeOpen' import {Envelope_Open_Stroke2_Corner0_Rounded as EnvelopeOpen} from '#/components/icons/EnveopeOpen'
import {Trash_Stroke2_Corner0_Rounded} from '#/components/icons/Trash' import {Trash_Stroke2_Corner0_Rounded} from '#/components/icons/Trash'
import {Link} from '#/components/Link'
import {useMenuControl} from '#/components/Menu' import {useMenuControl} from '#/components/Menu'
import {PostAlerts} from '#/components/moderation/PostAlerts' import {PostAlerts} from '#/components/moderation/PostAlerts'
import {createPortalGroup} from '#/components/Portal' import {createPortalGroup} from '#/components/Portal'
@@ -47,7 +45,6 @@ import {Text} from '#/components/Typography'
import {useSimpleVerificationState} from '#/components/verification' import {useSimpleVerificationState} from '#/components/verification'
import {VerificationCheck} from '#/components/verification/VerificationCheck' import {VerificationCheck} from '#/components/verification/VerificationCheck'
import type * as bsky from '#/types/bsky' import type * as bsky from '#/types/bsky'
import {Button} from '#/components/Button'
export const ChatListItemPortal = createPortalGroup() export const ChatListItemPortal = createPortalGroup()
@@ -88,7 +85,6 @@ function ChatListItemReady({
convo, convo,
profile: profileUnshadowed, profile: profileUnshadowed,
moderationOpts, moderationOpts,
showMenu,
children, children,
}: { }: {
convo: ChatBskyConvoDefs.ConvoView convo: ChatBskyConvoDefs.ConvoView
@@ -102,7 +98,6 @@ function ChatListItemReady({
const {currentAccount} = useSession() const {currentAccount} = useSession()
const menuControl = useMenuControl() const menuControl = useMenuControl()
const leaveConvoControl = useDialogControl() const leaveConvoControl = useDialogControl()
const {gtMobile} = useBreakpoints()
const profile = useProfileShadow(profileUnshadowed) const profile = useProfileShadow(profileUnshadowed)
const {mutate: markAsRead} = useMarkAsReadMutation() const {mutate: markAsRead} = useMarkAsReadMutation()
const moderation = React.useMemo( const moderation = React.useMemo(
@@ -116,17 +111,6 @@ function ChatListItemReady({
profile, profile,
}) })
const blockInfo = useMemo(() => {
const modui = moderation.ui('profileView')
const blocks = modui.alerts.filter(alert => alert.type === 'blocking')
const listBlocks = blocks.filter(alert => alert.source.type === 'list')
const userBlock = blocks.find(alert => alert.source.type === 'user')
return {
listBlocks,
userBlock,
}
}, [moderation])
const isDeletedAccount = profile.handle === 'missing.invalid' const isDeletedAccount = profile.handle === 'missing.invalid'
const displayName = isDeletedAccount const displayName = isDeletedAccount
? _(msg`Deleted Account`) ? _(msg`Deleted Account`)
@@ -137,137 +121,134 @@ function ChatListItemReady({
const isDimStyle = convo.muted || moderation.blocked || isDeletedAccount const isDimStyle = convo.muted || moderation.blocked || isDeletedAccount
const {lastMessage, lastMessageSentAt, latestReportableMessage} = const {lastMessage, lastMessageSentAt} = useMemo(() => {
useMemo(() => { // eslint-disable-next-line @typescript-eslint/no-shadow
// eslint-disable-next-line @typescript-eslint/no-shadow let lastMessage = _(msg`No messages yet`)
let lastMessage = _(msg`No messages yet`) // eslint-disable-next-line @typescript-eslint/no-shadow
// eslint-disable-next-line @typescript-eslint/no-shadow let lastMessageSentAt: string | null = null
let lastMessageSentAt: string | null = null
// eslint-disable-next-line @typescript-eslint/no-shadow
let latestReportableMessage: ChatBskyConvoDefs.MessageView | undefined
if (ChatBskyConvoDefs.isMessageView(convo.lastMessage)) { let latestReportableMessage: ChatBskyConvoDefs.MessageView | undefined
const isFromMe = convo.lastMessage.sender?.did === currentAccount?.did
if (!isFromMe) { if (ChatBskyConvoDefs.isMessageView(convo.lastMessage)) {
latestReportableMessage = convo.lastMessage const isFromMe = convo.lastMessage.sender?.did === currentAccount?.did
if (!isFromMe) {
latestReportableMessage = convo.lastMessage
}
if (convo.lastMessage.text) {
if (isFromMe) {
lastMessage = _(msg`You: ${convo.lastMessage.text}`)
} else {
lastMessage = convo.lastMessage.text
} }
} else if (convo.lastMessage.embed) {
const defaultEmbeddedContentMessage = _(
msg`(contains embedded content)`,
)
if (convo.lastMessage.text) { if (AppBskyEmbedRecord.isView(convo.lastMessage.embed)) {
if (isFromMe) { const embed = convo.lastMessage.embed
lastMessage = _(msg`You: ${convo.lastMessage.text}`)
} else {
lastMessage = convo.lastMessage.text
}
} else if (convo.lastMessage.embed) {
const defaultEmbeddedContentMessage = _(
msg`(contains embedded content)`,
)
if (AppBskyEmbedRecord.isView(convo.lastMessage.embed)) { if (AppBskyEmbedRecord.isViewRecord(embed.record)) {
const embed = convo.lastMessage.embed const record = embed.record
const path = postUriToRelativePath(record.uri, {
if (AppBskyEmbedRecord.isViewRecord(embed.record)) { handle: record.author.handle,
const record = embed.record })
const path = postUriToRelativePath(record.uri, { const href = path ? toBskyAppUrl(path) : undefined
handle: record.author.handle, const short = href
}) ? toShortUrl(href)
const href = path ? toBskyAppUrl(path) : undefined : defaultEmbeddedContentMessage
const short = href
? toShortUrl(href)
: defaultEmbeddedContentMessage
if (isFromMe) {
lastMessage = _(msg`You: ${short}`)
} else {
lastMessage = short
}
}
} else {
if (isFromMe) { if (isFromMe) {
lastMessage = _(msg`You: ${defaultEmbeddedContentMessage}`) lastMessage = _(msg`You: ${short}`)
} else { } else {
lastMessage = defaultEmbeddedContentMessage lastMessage = short
} }
} }
} } else {
lastMessageSentAt = convo.lastMessage.sentAt
}
if (ChatBskyConvoDefs.isDeletedMessageView(convo.lastMessage)) {
lastMessageSentAt = convo.lastMessage.sentAt
lastMessage = isDeletedAccount
? _(msg`Conversation deleted`)
: _(msg`Message deleted`)
}
if (ChatBskyConvoDefs.isMessageAndReactionView(convo.lastReaction)) {
if (
!lastMessageSentAt ||
new Date(lastMessageSentAt) <
new Date(convo.lastReaction.reaction.createdAt)
) {
const isFromMe =
convo.lastReaction.reaction.sender.did === currentAccount?.did
const lastMessageText = convo.lastReaction.message.text
const fallbackMessage = _(
msg({
message: 'a message',
comment: `If last message does not contain text, fall back to "{user} reacted to {a message}"`,
}),
)
if (isFromMe) { if (isFromMe) {
lastMessage = _(msg`You: ${defaultEmbeddedContentMessage}`)
} else {
lastMessage = defaultEmbeddedContentMessage
}
}
}
lastMessageSentAt = convo.lastMessage.sentAt
}
if (ChatBskyConvoDefs.isDeletedMessageView(convo.lastMessage)) {
lastMessageSentAt = convo.lastMessage.sentAt
lastMessage = isDeletedAccount
? _(msg`Conversation deleted`)
: _(msg`Message deleted`)
}
if (ChatBskyConvoDefs.isMessageAndReactionView(convo.lastReaction)) {
if (
!lastMessageSentAt ||
new Date(lastMessageSentAt) <
new Date(convo.lastReaction.reaction.createdAt)
) {
const isFromMe =
convo.lastReaction.reaction.sender.did === currentAccount?.did
const lastMessageText = convo.lastReaction.message.text
const fallbackMessage = _(
msg({
message: 'a message',
comment: `If last message does not contain text, fall back to "{user} reacted to {a message}"`,
}),
)
if (isFromMe) {
lastMessage = _(
msg`You reacted ${convo.lastReaction.reaction.value} to ${
lastMessageText
? `"${convo.lastReaction.message.text}"`
: fallbackMessage
}`,
)
} else {
const senderDid = convo.lastReaction.reaction.sender.did
const sender = convo.members.find(member => member.did === senderDid)
if (sender) {
lastMessage = _( lastMessage = _(
msg`You reacted ${convo.lastReaction.reaction.value} to ${ msg`${sanitizeDisplayName(
sender.displayName || sender.handle,
)} reacted ${convo.lastReaction.reaction.value} to ${
lastMessageText lastMessageText
? `"${convo.lastReaction.message.text}"` ? `"${convo.lastReaction.message.text}"`
: fallbackMessage : fallbackMessage
}`, }`,
) )
} else { } else {
const senderDid = convo.lastReaction.reaction.sender.did lastMessage = _(
const sender = convo.members.find( msg`Someone reacted ${convo.lastReaction.reaction.value} to ${
member => member.did === senderDid, lastMessageText
? `"${convo.lastReaction.message.text}"`
: fallbackMessage
}`,
) )
if (sender) {
lastMessage = _(
msg`${sanitizeDisplayName(
sender.displayName || sender.handle,
)} reacted ${convo.lastReaction.reaction.value} to ${
lastMessageText
? `"${convo.lastReaction.message.text}"`
: fallbackMessage
}`,
)
} else {
lastMessage = _(
msg`Someone reacted ${convo.lastReaction.reaction.value} to ${
lastMessageText
? `"${convo.lastReaction.message.text}"`
: fallbackMessage
}`,
)
}
} }
} }
} }
}
return { return {
lastMessage, lastMessage,
lastMessageSentAt, lastMessageSentAt,
latestReportableMessage, latestReportableMessage,
} }
}, [ }, [
_, _,
convo.lastMessage, convo.lastMessage,
convo.lastReaction, convo.lastReaction,
currentAccount?.did, currentAccount?.did,
isDeletedAccount, isDeletedAccount,
convo.members, convo.members,
]) ])
const [showActions, setShowActions] = useState(false) const [_showActions, setShowActions] = useState(false)
const onMouseEnter = useCallback(() => { const onMouseEnter = useCallback(() => {
setShowActions(true) setShowActions(true)
@@ -2,10 +2,8 @@ import {useCallback} from 'react'
import {type ChatBskyActorDefs, ChatBskyConvoDefs} from '@atproto/api' import {type ChatBskyActorDefs, ChatBskyConvoDefs} from '@atproto/api'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {StackActions, useNavigation} from '@react-navigation/native'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {type NavigationProp} from '#/lib/routes/types'
import {useProfileShadow} from '#/state/cache/profile-shadow' import {useProfileShadow} from '#/state/cache/profile-shadow'
import {useEmail} from '#/state/email-verification' import {useEmail} from '#/state/email-verification'
import {useAcceptConversation} from '#/state/queries/messages/accept-conversation' import {useAcceptConversation} from '#/state/queries/messages/accept-conversation'
@@ -5,7 +5,6 @@ import {Trans} from '@lingui/macro'
import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {atoms as a, tokens} from '#/alf' import {atoms as a, tokens} from '#/alf'
import {KnownFollowers} from '#/components/KnownFollowers'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {ChatListItem, ChatListItemPortal} from './ChatListItem' import {ChatListItem, ChatListItemPortal} from './ChatListItem'
import {AcceptChatButton, DeleteChatButton, RejectMenu} from './RequestButtons' import {AcceptChatButton, DeleteChatButton, RejectMenu} from './RequestButtons'