[🐴] Post embeds polish (#4339)

* Handle message cleanup

* Handle last message in chat list

* Memoize lastMessage
zio/stable
Eric Bailey 2024-06-03 20:07:01 -05:00 committed by GitHub
parent da96fb1ef5
commit de93e8de74
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 94 additions and 30 deletions

View File

@ -3,6 +3,7 @@ import psl from 'psl'
import TLDs from 'tlds'
import {BSKY_SERVICE} from 'lib/constants'
import {isInvalidHandle} from 'lib/strings/handles'
export const BSKY_APP_HOST = 'https://bsky.app'
const BSKY_TRUSTED_HOSTS = [
@ -83,6 +84,10 @@ export function toShareUrl(url: string): string {
return url
}
export function toBskyAppUrl(url: string): string {
return new URL(url, BSKY_APP_HOST).toString()
}
export function isBskyAppUrl(url: string): boolean {
return url.startsWith('https://bsky.app/')
}
@ -183,6 +188,22 @@ export function feedUriToHref(url: string): string {
}
}
export function postUriToRelativePath(
uri: string,
options?: {handle?: string},
): string | undefined {
try {
const {hostname, rkey} = new AtUri(uri)
const handleOrDid =
options?.handle && !isInvalidHandle(options.handle)
? options.handle
: hostname
return `/profile/${handleOrDid}/post/${rkey}`
} catch {
return undefined
}
}
/**
* Checks if the label in the post text matches the host of the link facet.
*

View File

@ -312,25 +312,19 @@ export function MessagesList({
})
if (postLinkFacet) {
// remove the post link from the text
rt.delete(
postLinkFacet.index.byteStart,
postLinkFacet.index.byteEnd,
)
const isAtStart = postLinkFacet.index.byteStart === 0
const isAtEnd =
postLinkFacet.index.byteEnd === rt.unicodeText.graphemeLength
// re-trim the text, now that we've removed the post link
//
// if the post link is at the start of the text, we don't want to leave a leading space
// so trim on both sides
if (postLinkFacet.index.byteStart === 0) {
rt = new RichText({text: rt.text.trim()}, {cleanNewlines: true})
} else {
// otherwise just trim the end
rt = new RichText(
{text: rt.text.trimEnd()},
{cleanNewlines: true},
// remove the post link from the text
if (isAtStart || isAtEnd) {
rt.delete(
postLinkFacet.index.byteStart,
postLinkFacet.index.byteEnd,
)
}
rt = new RichText({text: rt.text.trim()}, {cleanNewlines: true})
}
}
} catch (error) {

View File

@ -2,6 +2,7 @@ import React, {useCallback, useState} from 'react'
import {GestureResponderEvent, View} from 'react-native'
import {
AppBskyActorDefs,
AppBskyEmbedRecord,
ChatBskyConvoDefs,
moderateProfile,
ModerationOpts,
@ -9,6 +10,11 @@ import {
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {
postUriToRelativePath,
toBskyAppUrl,
toShortUrl,
} from '#/lib/strings/url-helpers'
import {isNative} from '#/platform/detection'
import {useProfileShadow} from '#/state/cache/profile-shadow'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
@ -95,21 +101,64 @@ function ChatListItemReady({
const isDimStyle = convo.muted || moderation.blocked || isDeletedAccount
let lastMessage = _(msg`No messages yet`)
let lastMessageSentAt: string | null = null
if (ChatBskyConvoDefs.isMessageView(convo.lastMessage)) {
if (convo.lastMessage.sender?.did === currentAccount?.did) {
lastMessage = _(msg`You: ${convo.lastMessage.text}`)
} else {
lastMessage = convo.lastMessage.text
const {lastMessage, lastMessageSentAt} = React.useMemo(() => {
let lastMessage = _(msg`No messages yet`)
let lastMessageSentAt: string | null = null
if (ChatBskyConvoDefs.isMessageView(convo.lastMessage)) {
const isFromMe = convo.lastMessage.sender?.did === currentAccount?.did
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 (AppBskyEmbedRecord.isView(convo.lastMessage.embed)) {
const embed = convo.lastMessage.embed
if (AppBskyEmbedRecord.isViewRecord(embed.record)) {
const record = embed.record
const path = postUriToRelativePath(record.uri, {
handle: record.author.handle,
})
const href = path ? toBskyAppUrl(path) : undefined
const short = href
? toShortUrl(href)
: defaultEmbeddedContentMessage
if (isFromMe) {
lastMessage = _(msg`You: ${short}`)
} else {
lastMessage = short
}
}
} else {
if (isFromMe) {
lastMessage = _(msg`You: ${defaultEmbeddedContentMessage}`)
} else {
lastMessage = defaultEmbeddedContentMessage
}
}
}
lastMessageSentAt = convo.lastMessage.sentAt
}
lastMessageSentAt = convo.lastMessage.sentAt
}
if (ChatBskyConvoDefs.isDeletedMessageView(convo.lastMessage)) {
lastMessage = isDeletedAccount
? _(msg`Conversation deleted`)
: _(msg`Message deleted`)
}
if (ChatBskyConvoDefs.isDeletedMessageView(convo.lastMessage)) {
lastMessage = isDeletedAccount
? _(msg`Conversation deleted`)
: _(msg`Message deleted`)
}
return {
lastMessage,
lastMessageSentAt,
}
}, [_, convo.lastMessage, currentAccount?.did, isDeletedAccount])
const [showActions, setShowActions] = useState(false)