add reqId to feed feedback (#8396)

Co-authored-by: Samuel Newman <mozzius@protonmail.com>
This commit is contained in:
hailey
2025-05-21 11:15:55 -07:00
committed by GitHub
parent e6c867a961
commit c16cd36b64
14 changed files with 200 additions and 183 deletions
+2 -2
View File
@@ -69,7 +69,7 @@
"icons:optimize": "svgo -f ./assets/icons"
},
"dependencies": {
"@atproto/api": "^0.15.7",
"@atproto/api": "^0.15.8",
"@bitdrift/react-native": "^0.6.8",
"@braintree/sanitize-url": "^6.0.2",
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
@@ -219,7 +219,7 @@
"zod": "^3.20.2"
},
"devDependencies": {
"@atproto/dev-env": "^0.3.131",
"@atproto/dev-env": "^0.3.132",
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@babel/runtime": "^7.26.0",
+6 -2
View File
@@ -1,5 +1,5 @@
import {
AppBskyActorDefs,
type AppBskyActorDefs,
AppBskyEmbedRecord,
AppBskyEmbedRecordWithMedia,
AppBskyFeedDefs,
@@ -9,7 +9,7 @@ import {
import * as bsky from '#/types/bsky'
import {isPostInLanguage} from '../../locale/helpers'
import {FALLBACK_MARKER_POST} from './feed/home'
import {ReasonFeedSource} from './feed/types'
import {type ReasonFeedSource} from './feed/types'
type FeedViewPost = AppBskyFeedDefs.FeedViewPost
@@ -187,6 +187,10 @@ export class FeedViewPostsSlice {
return this._feedPost.feedContext
}
get reqId() {
return this._feedPost.reqId
}
get isRepost() {
const reason = this._feedPost.reason
return AppBskyFeedDefs.isReasonRepost(reason)
+1
View File
@@ -882,6 +882,7 @@ export function Explore({
record={subItem.record}
reason={indexInSlice === 0 ? slice.reason : undefined}
feedContext={slice.feedContext}
reqId={slice.reqId}
moderation={subItem.moderation}
parentAuthor={subItem.parentAuthor}
showReplyTo={item.showReplyTo}
+15 -1
View File
@@ -178,6 +178,7 @@ type VideoItem = {
post: AppBskyFeedDefs.PostView
video: AppBskyEmbedVideo.View
feedContext: string | undefined
reqId: string | undefined
}
function Feed() {
@@ -216,6 +217,7 @@ function Feed() {
post: AppBskyFeedDefs.PostView
video: AppBskyEmbedVideo.View
feedContext: string | undefined
reqId: string | undefined
}[] = []
for (const slice of page.slices) {
const feedPost = slice.items.find(
@@ -228,6 +230,7 @@ function Feed() {
post: feedPost.post,
video: feedPost.post.embed,
feedContext: slice.feedContext,
reqId: slice.reqId,
})
}
}
@@ -274,6 +277,7 @@ function Feed() {
moderation={item.moderation}
scrollGesture={scrollGesture}
feedContext={item.feedContext}
reqId={item.reqId}
/>
)
},
@@ -470,6 +474,7 @@ let VideoItem = ({
scrollGesture,
moderation,
feedContext,
reqId,
}: {
player?: VideoPlayer
post: AppBskyFeedDefs.PostView
@@ -479,6 +484,7 @@ let VideoItem = ({
scrollGesture: NativeGesture
moderation?: ModerationDecision
feedContext: string | undefined
reqId: string | undefined
}): React.ReactNode => {
const postShadow = usePostShadow(post)
const {width, height} = useSafeAreaFrame()
@@ -490,9 +496,10 @@ let VideoItem = ({
item: post.uri,
event: 'app.bsky.feed.defs#interactionSeen',
feedContext,
reqId,
})
}
}, [active, post.uri, feedContext, sendInteraction])
}, [active, post.uri, feedContext, reqId, sendInteraction])
// TODO: high-performance android phones should also
// be capable of rendering 3 video players, but currently
@@ -537,6 +544,7 @@ let VideoItem = ({
scrollGesture={scrollGesture}
moderation={moderation}
feedContext={feedContext}
reqId={reqId}
/>
)}
</>
@@ -682,6 +690,7 @@ function Overlay({
scrollGesture,
moderation,
feedContext,
reqId,
}: {
player?: VideoPlayer
post: Shadow<AppBskyFeedDefs.PostView>
@@ -690,6 +699,7 @@ function Overlay({
scrollGesture: NativeGesture
moderation: ModerationDecision
feedContext: string | undefined
reqId: string | undefined
}) {
const {_} = useLingui()
const t = useTheme()
@@ -760,6 +770,7 @@ function Overlay({
player={player}
post={post}
feedContext={feedContext}
reqId={reqId}
/>
)}
</View>
@@ -1002,10 +1013,12 @@ function PlayPauseTapArea({
player,
post,
feedContext,
reqId,
}: {
player: VideoPlayer
post: Shadow<AppBskyFeedDefs.PostView>
feedContext: string | undefined
reqId: string | undefined
}) {
const {_} = useLingui()
const doubleTapRef = useRef<ReturnType<typeof setTimeout> | null>(null)
@@ -1036,6 +1049,7 @@ function PlayPauseTapArea({
item: post.uri,
event: 'app.bsky.feed.defs#interactionLike',
feedContext,
reqId,
})
} else {
doubleTapRef.current = setTimeout(togglePlayPause, 200)
+11 -7
View File
@@ -1,12 +1,15 @@
import React from 'react'
import {AppState, AppStateStatus} from 'react-native'
import {AppBskyFeedDefs} from '@atproto/api'
import {AppState, type AppStateStatus} from 'react-native'
import {type AppBskyFeedDefs} from '@atproto/api'
import throttle from 'lodash.throttle'
import {FEEDBACK_FEEDS, STAGING_FEEDS} from '#/lib/constants'
import {logEvent} from '#/lib/statsig/statsig'
import {logger} from '#/logger'
import {FeedDescriptor, FeedPostSliceItem} from '#/state/queries/post-feed'
import {
type FeedDescriptor,
type FeedPostSliceItem,
} from '#/state/queries/post-feed'
import {getItemsForFeedback} from '#/view/com/posts/PostFeed'
import {useAgent} from './session'
@@ -103,7 +106,7 @@ export function useFeedFeedback(feed: FeedDescriptor, hasSession: boolean) {
return
}
const items = getItemsForFeedback(feedItem)
for (const {item: postItem, feedContext} of items) {
for (const {item: postItem, feedContext, reqId} of items) {
if (!history.current.has(postItem)) {
history.current.add(postItem)
queue.current.add(
@@ -111,6 +114,7 @@ export function useFeedFeedback(feed: FeedDescriptor, hasSession: boolean) {
item: postItem.uri,
event: 'app.bsky.feed.defs#interactionSeen',
feedContext,
reqId,
}),
)
sendToFeed()
@@ -164,12 +168,12 @@ function isDiscoverFeed(feed: FeedDescriptor) {
function toString(interaction: AppBskyFeedDefs.Interaction): string {
return `${interaction.item}|${interaction.event}|${
interaction.feedContext || ''
}`
}|${interaction.reqId || ''}`
}
function toInteraction(str: string): AppBskyFeedDefs.Interaction {
const [item, event, feedContext] = str.split('|')
return {item, event, feedContext}
const [item, event, feedContext, reqId] = str.split('|')
return {item, event, feedContext, reqId}
}
type AggregatedStats = {
@@ -215,6 +215,7 @@ export function useFeedPreviews(
isFallbackMarker: false,
isIncompleteThread: item.isIncompleteThread,
feedContext: item.feedContext,
reqId: item.reqId,
reason: item.reason,
feedPostUri: item.feedPostUri,
items: item.items
+3
View File
@@ -92,6 +92,7 @@ export interface FeedPostSlice {
isIncompleteThread: boolean
isFallbackMarker: boolean
feedContext: string | undefined
reqId: string | undefined
feedPostUri: string
reason?:
| AppBskyFeedDefs.ReasonRepost
@@ -316,6 +317,7 @@ export function usePostFeedQuery(
userActionHistory.seen(
slice.items.map(item => ({
feedContext: slice.feedContext,
reqId: slice.reqId,
likeCount: item.post.likeCount ?? 0,
repostCount: item.post.repostCount ?? 0,
replyCount: item.post.replyCount ?? 0,
@@ -333,6 +335,7 @@ export function usePostFeedQuery(
isIncompleteThread: slice.isIncompleteThread,
isFallbackMarker: slice.isFallbackMarker,
feedContext: slice.feedContext,
reqId: slice.reqId,
reason: slice.reason,
feedPostUri: slice.feedPostUri,
items: slice.items.map((item, i) => {
+18 -2
View File
@@ -103,6 +103,7 @@ type FeedRow =
items: FeedPostSliceItem[]
sourceFeedUri: string
feedContexts: (string | undefined)[]
reqIds: (string | undefined)[]
}
| {
type: 'sliceViewFullThread'
@@ -134,16 +135,19 @@ export function getItemsForFeedback(feedRow: FeedRow):
| {
item: FeedPostSliceItem
feedContext: string | undefined
reqId: string | undefined
}[] {
if (feedRow.type === 'sliceItem') {
return feedRow.slice.items.map(item => ({
item,
feedContext: feedRow.slice.feedContext,
reqId: feedRow.slice.reqId,
}))
} else if (feedRow.type === 'videoGridRow') {
return feedRow.items.map((item, i) => ({
item,
feedContext: feedRow.feedContexts[i],
reqId: feedRow.reqIds[i],
}))
} else {
return []
@@ -398,6 +402,7 @@ let PostFeed = ({
const videos: {
item: FeedPostSliceItem
feedContext: string | undefined
reqId: string | undefined
}[] = []
for (const page of data.pages) {
for (const slice of page.slices) {
@@ -405,7 +410,11 @@ let PostFeed = ({
item => item.uri === slice.feedPostUri,
)
if (item && AppBskyEmbedVideo.isView(item.post.embed)) {
videos.push({item, feedContext: slice.feedContext})
videos.push({
item,
feedContext: slice.feedContext,
reqId: slice.reqId,
})
}
}
}
@@ -413,12 +422,17 @@ let PostFeed = ({
const rows: {
item: FeedPostSliceItem
feedContext: string | undefined
reqId: string | undefined
}[][] = []
for (let i = 0; i < videos.length; i++) {
const video = videos[i]
const item = video.item
const cols = gtMobile ? 3 : 2
const rowItem = {item, feedContext: video.feedContext}
const rowItem = {
item,
feedContext: video.feedContext,
reqId: video.reqId,
}
if (i % cols === 0) {
rows.push([rowItem])
} else {
@@ -434,6 +448,7 @@ let PostFeed = ({
items: row.map(r => r.item),
sourceFeedUri: feedUriOrActorDid,
feedContexts: row.map(r => r.feedContext),
reqIds: row.map(r => r.reqId),
})
}
} else {
@@ -685,6 +700,7 @@ let PostFeed = ({
record={item.record}
reason={indexInSlice === 0 ? slice.reason : undefined}
feedContext={slice.feedContext}
reqId={slice.reqId}
moderation={item.moderation}
parentAuthor={item.parentAuthor}
showReplyTo={row.showReplyTo}
+20 -10
View File
@@ -70,6 +70,7 @@ interface FeedItemProps {
isThreadLastChild?: boolean
isThreadParent?: boolean
feedContext: string | undefined
reqId: string | undefined
hideTopBorder?: boolean
isParentBlocked?: boolean
isParentNotFound?: boolean
@@ -80,6 +81,7 @@ export function PostFeedItem({
record,
reason,
feedContext,
reqId,
moderation,
parentAuthor,
showReplyTo,
@@ -117,6 +119,7 @@ export function PostFeedItem({
record={record}
reason={reason}
feedContext={feedContext}
reqId={reqId}
richText={richText}
parentAuthor={parentAuthor}
showReplyTo={showReplyTo}
@@ -140,6 +143,7 @@ let FeedItemInner = ({
record,
reason,
feedContext,
reqId,
richText,
moderation,
parentAuthor,
@@ -171,11 +175,12 @@ let FeedItemInner = ({
}, [post.uri, post.author])
const {sendInteraction} = useFeedFeedbackContext()
const onPressReply = useCallback(() => {
const onPressReply = () => {
sendInteraction({
item: post.uri,
event: 'app.bsky.feed.defs#interactionReply',
feedContext,
reqId,
})
openComposer({
replyTo: {
@@ -187,40 +192,44 @@ let FeedItemInner = ({
moderation,
},
})
}, [post, record, openComposer, moderation, sendInteraction, feedContext])
}
const onOpenAuthor = useCallback(() => {
const onOpenAuthor = () => {
sendInteraction({
item: post.uri,
event: 'app.bsky.feed.defs#clickthroughAuthor',
feedContext,
reqId,
})
}, [sendInteraction, post, feedContext])
}
const onOpenReposter = useCallback(() => {
const onOpenReposter = () => {
sendInteraction({
item: post.uri,
event: 'app.bsky.feed.defs#clickthroughReposter',
feedContext,
reqId,
})
}, [sendInteraction, post, feedContext])
}
const onOpenEmbed = useCallback(() => {
const onOpenEmbed = () => {
sendInteraction({
item: post.uri,
event: 'app.bsky.feed.defs#clickthroughEmbed',
feedContext,
reqId,
})
}, [sendInteraction, post, feedContext])
}
const onBeforePress = useCallback(() => {
const onBeforePress = () => {
sendInteraction({
item: post.uri,
event: 'app.bsky.feed.defs#clickthroughItem',
feedContext,
reqId,
})
precacheProfile(queryClient, post.author)
}, [queryClient, post, sendInteraction, feedContext])
}
const outerStyles = [
styles.outer,
@@ -437,6 +446,7 @@ let FeedItemInner = ({
onPressReply={onPressReply}
logContext="FeedItem"
feedContext={feedContext}
reqId={reqId}
threadgateRecord={threadgateRecord}
onShowLess={onShowLess}
/>
@@ -28,6 +28,7 @@ let PostDropdownBtn = ({
testID,
post,
postFeedContext,
postReqId,
record,
richText,
style,
@@ -40,6 +41,7 @@ let PostDropdownBtn = ({
testID: string
post: Shadow<AppBskyFeedDefs.PostView>
postFeedContext: string | undefined
postReqId: string | undefined
record: AppBskyFeedPost.Record
richText: RichTextAPI
style?: StyleProp<ViewStyle>
@@ -99,6 +101,7 @@ let PostDropdownBtn = ({
testID={testID}
post={post}
postFeedContext={postFeedContext}
postReqId={postReqId}
record={record}
richText={richText}
timestamp={timestamp}
@@ -1,4 +1,4 @@
import React, {memo, useCallback} from 'react'
import React, {memo} from 'react'
import {
Platform,
type PressableProps,
@@ -97,6 +97,7 @@ import * as Toast from '../Toast'
let PostDropdownMenuItems = ({
post,
postFeedContext,
postReqId,
record,
richText,
timestamp,
@@ -106,6 +107,7 @@ let PostDropdownMenuItems = ({
testID: string
post: Shadow<AppBskyFeedDefs.PostView>
postFeedContext: string | undefined
postReqId: string | undefined
record: AppBskyFeedPost.Record
richText: RichTextAPI
style?: StyleProp<ViewStyle>
@@ -189,7 +191,7 @@ let PostDropdownMenuItems = ({
langPrefs.primaryLanguage,
)
const onDeletePost = React.useCallback(() => {
const onDeletePost = () => {
deletePostMutate({uri: postUri}).then(
() => {
Toast.show(_(msg({message: 'Post deleted', context: 'toast'})))
@@ -215,18 +217,9 @@ let PostDropdownMenuItems = ({
Toast.show(_(msg`Failed to delete post, please try again`), 'xmark')
},
)
}, [
navigation,
postUri,
deletePostMutate,
postAuthor,
currentAccount,
isAuthor,
href,
_,
])
}
const onToggleThreadMute = React.useCallback(() => {
const onToggleThreadMute = () => {
try {
if (isThreadMuted) {
unmuteThread()
@@ -246,16 +239,16 @@ let PostDropdownMenuItems = ({
)
}
}
}, [isThreadMuted, unmuteThread, _, muteThread])
}
const onCopyPostText = React.useCallback(() => {
const onCopyPostText = () => {
const str = richTextToString(richText, true)
Clipboard.setStringAsync(str)
Toast.show(_(msg`Copied to clipboard`), 'clipboard-check')
}, [_, richText])
}
const onPressTranslate = React.useCallback(async () => {
const onPressTranslate = async () => {
await openLink(translatorUrl, true)
if (
@@ -270,40 +263,40 @@ let PostDropdownMenuItems = ({
textLength: post.record.text.length,
})
}
}, [openLink, translatorUrl, langPrefs, post])
}
const onHidePost = React.useCallback(() => {
const onHidePost = () => {
hidePost({uri: postUri})
}, [postUri, hidePost])
}
const hideInPWI = React.useMemo(() => {
return !!postAuthor.labels?.find(
label => label.val === '!no-unauthenticated',
)
}, [postAuthor])
const hideInPWI = !!postAuthor.labels?.find(
label => label.val === '!no-unauthenticated',
)
const showLoggedOutWarning =
postAuthor.did !== currentAccount?.did && hideInPWI
const onSharePost = React.useCallback(() => {
const onSharePost = () => {
const url = toShareUrl(href)
shareUrl(url)
}, [href])
}
const onPressShowMore = React.useCallback(() => {
const onPressShowMore = () => {
feedFeedback.sendInteraction({
event: 'app.bsky.feed.defs#requestMore',
item: postUri,
feedContext: postFeedContext,
reqId: postReqId,
})
Toast.show(_(msg({message: 'Feedback sent!', context: 'toast'})))
}, [feedFeedback, postUri, postFeedContext, _])
}
const onPressShowLess = React.useCallback(() => {
const onPressShowLess = () => {
feedFeedback.sendInteraction({
event: 'app.bsky.feed.defs#requestLess',
item: postUri,
feedContext: postFeedContext,
reqId: postReqId,
})
if (onShowLess) {
onShowLess({
@@ -313,19 +306,16 @@ let PostDropdownMenuItems = ({
} else {
Toast.show(_(msg({message: 'Feedback sent!', context: 'toast'})))
}
}, [feedFeedback, postUri, postFeedContext, _, onShowLess])
}
const onSelectChatToShareTo = React.useCallback(
(conversation: string) => {
navigation.navigate('MessagesConversation', {
conversation,
embed: postUri,
})
},
[navigation, postUri],
)
const onSelectChatToShareTo = (conversation: string) => {
navigation.navigate('MessagesConversation', {
conversation,
embed: postUri,
})
}
const onToggleQuotePostAttachment = React.useCallback(async () => {
const onToggleQuotePostAttachment = async () => {
if (!quoteEmbed) return
const action = quoteEmbed.isDetached ? 'reattach' : 'detach'
@@ -348,7 +338,7 @@ let PostDropdownMenuItems = ({
)
logger.error(`Failed to ${action} quote`, {safeMessage: e.message})
}
}, [_, quoteEmbed, post, toggleQuoteDetachment])
}
const canHidePostForMe = !isAuthor && !isPostHidden
const canEmbed = isWeb && gtMobile && !hideInPWI
@@ -356,7 +346,7 @@ let PostDropdownMenuItems = ({
!isAuthor && isRootPostAuthor && !isPostHidden && isReply
const canDetachQuote = quoteEmbed && quoteEmbed.isOwnedByViewer
const onToggleReplyVisibility = React.useCallback(async () => {
const onToggleReplyVisibility = async () => {
// TODO no threadgate?
if (!canHideReplyForEveryone) return
@@ -380,25 +370,18 @@ let PostDropdownMenuItems = ({
)
logger.error(`Failed to ${action} reply`, {safeMessage: e.message})
}
}, [
_,
isReplyHiddenByThreadgate,
rootUri,
postUri,
canHideReplyForEveryone,
toggleReplyVisibility,
])
}
const onPressPin = useCallback(() => {
const onPressPin = () => {
logEvent(isPinned ? 'post:unpin' : 'post:pin', {})
pinPostMutate({
postUri,
postCid,
action: isPinned ? 'unpin' : 'pin',
})
}, [isPinned, pinPostMutate, postCid, postUri])
}
const onBlockAuthor = useCallback(async () => {
const onBlockAuthor = async () => {
try {
await queueBlock()
Toast.show(_(msg({message: 'Account blocked', context: 'toast'})))
@@ -408,9 +391,9 @@ let PostDropdownMenuItems = ({
Toast.show(_(msg`There was an issue! ${e.toString()}`), 'xmark')
}
}
}, [_, queueBlock])
}
const onMuteAuthor = useCallback(async () => {
const onMuteAuthor = async () => {
if (postAuthor.viewer?.muted) {
try {
await queueUnmute()
@@ -432,22 +415,22 @@ let PostDropdownMenuItems = ({
}
}
}
}, [_, queueMute, queueUnmute, postAuthor.viewer?.muted])
}
const onShareATURI = useCallback(() => {
const onShareATURI = () => {
shareText(postUri)
}, [postUri])
}
const onShareAuthorDID = useCallback(() => {
const onShareAuthorDID = () => {
shareText(postAuthor.did)
}, [postAuthor.did])
}
const onReportMisclassification = useCallback(() => {
const onReportMisclassification = () => {
const url = `https://docs.google.com/forms/d/e/1FAIpQLSd0QPqhNFksDQf1YyOos7r1ofCLvmrKAH1lU042TaS3GAZaWQ/viewform?entry.1756031717=${toShareUrl(
href,
)}`
openLink(url)
}, [href, openLink])
}
return (
<>
+16 -37
View File
@@ -1,4 +1,4 @@
import React, {memo, useCallback} from 'react'
import React, {memo} from 'react'
import {
Pressable,
type PressableStateCallbackType,
@@ -55,6 +55,7 @@ let PostCtrls = ({
record,
richText,
feedContext,
reqId,
style,
onPressReply,
onPostReply,
@@ -67,6 +68,7 @@ let PostCtrls = ({
record: AppBskyFeedPost.Record
richText: RichTextAPI
feedContext?: string | undefined
reqId?: string | undefined
style?: StyleProp<ViewStyle>
onPressReply: () => void
onPostReply?: (postUri: string | undefined) => void
@@ -117,7 +119,7 @@ let PostCtrls = ({
const [hasLikeIconBeenToggled, setHasLikeIconBeenToggled] =
React.useState(false)
const onPressToggleLike = React.useCallback(async () => {
const onPressToggleLike = async () => {
if (isBlocked) {
Toast.show(
_(msg`Cannot interact with a blocked user`),
@@ -134,6 +136,7 @@ let PostCtrls = ({
item: post.uri,
event: 'app.bsky.feed.defs#interactionLike',
feedContext,
reqId,
})
captureAction(ProgressGuideAction.Like)
await queueLike()
@@ -145,20 +148,9 @@ let PostCtrls = ({
throw e
}
}
}, [
_,
playHaptic,
post.uri,
post.viewer?.like,
queueLike,
queueUnlike,
sendInteraction,
captureAction,
feedContext,
isBlocked,
])
}
const onRepost = useCallback(async () => {
const onRepost = async () => {
if (isBlocked) {
Toast.show(
_(msg`Cannot interact with a blocked user`),
@@ -173,6 +165,7 @@ let PostCtrls = ({
item: post.uri,
event: 'app.bsky.feed.defs#interactionRepost',
feedContext,
reqId,
})
await queueRepost()
} else {
@@ -183,18 +176,9 @@ let PostCtrls = ({
throw e
}
}
}, [
_,
post.uri,
post.viewer?.repost,
queueRepost,
queueUnrepost,
sendInteraction,
feedContext,
isBlocked,
])
}
const onQuote = useCallback(() => {
const onQuote = () => {
if (isBlocked) {
Toast.show(
_(msg`Cannot interact with a blocked user`),
@@ -207,22 +191,15 @@ let PostCtrls = ({
item: post.uri,
event: 'app.bsky.feed.defs#interactionQuote',
feedContext,
reqId,
})
openComposer({
quote: post,
onPost: onPostReply,
})
}, [
_,
sendInteraction,
post,
feedContext,
openComposer,
onPostReply,
isBlocked,
])
}
const onShare = useCallback(() => {
const onShare = () => {
const urip = new AtUri(post.uri)
const href = makeProfileLink(post.author, 'post', urip.rkey)
const url = toShareUrl(href)
@@ -231,8 +208,9 @@ let PostCtrls = ({
item: post.uri,
event: 'app.bsky.feed.defs#interactionShare',
feedContext,
reqId,
})
}, [post.uri, post.author, sendInteraction, feedContext])
}
const btnStyle = React.useCallback(
({pressed, hovered}: PressableStateCallbackType) => [
@@ -374,6 +352,7 @@ let PostCtrls = ({
testID="postDropdownBtn"
post={post}
postFeedContext={feedContext}
postReqId={reqId}
record={record}
richText={richText}
style={{padding: 5}}
+1
View File
@@ -829,6 +829,7 @@ function MockPostFeedItem({
showReplyTo={false}
reason={undefined}
feedContext={''}
reqId={undefined}
rootPost={post}
/>
)
+57 -59
View File
@@ -20,28 +20,27 @@
"@jridgewell/gen-mapping" "^0.3.0"
"@jridgewell/trace-mapping" "^0.3.9"
"@atproto-labs/fetch-node@0.1.8":
version "0.1.8"
resolved "https://registry.yarnpkg.com/@atproto-labs/fetch-node/-/fetch-node-0.1.8.tgz#687fc8be6107f10a4247c17989792862affd838b"
integrity sha512-OOTIhZNPEDDm7kaYU8iYRgzM+D5n3mP2iiBSyKuLakKTaZBL5WwYlUsJVsqX26SnUXtGEroOJEVJ6f66OcG80w==
"@atproto-labs/fetch-node@0.1.9":
version "0.1.9"
resolved "https://registry.yarnpkg.com/@atproto-labs/fetch-node/-/fetch-node-0.1.9.tgz#5df902413cc2ebfff914999ad3fbbc13b20e1dd0"
integrity sha512-8sHDDXZEzQptLu8ddUU/8U+THS6dumgPynVX0/1PjUYd4S/FWyPcz6yMIiVChTfzKnZvYRRz47+qvOKhydrHQw==
dependencies:
"@atproto-labs/fetch" "0.2.2"
"@atproto-labs/pipe" "0.1.0"
"@atproto-labs/fetch" "0.2.3"
"@atproto-labs/pipe" "0.1.1"
ipaddr.js "^2.1.0"
psl "^1.9.0"
undici "^6.14.1"
"@atproto-labs/fetch@0.2.2":
version "0.2.2"
resolved "https://registry.yarnpkg.com/@atproto-labs/fetch/-/fetch-0.2.2.tgz#c65acfd7b2265a8fe7d4ba3997126cce07bafe26"
integrity sha512-QyafkedbFeVaN20DYUpnY2hcArYxjdThPXbYMqOSoZhcvkrUqaw4xDND4wZB5TBD9cq2yqe9V6mcw9P4XQKQuQ==
"@atproto-labs/fetch@0.2.3":
version "0.2.3"
resolved "https://registry.yarnpkg.com/@atproto-labs/fetch/-/fetch-0.2.3.tgz#d47afec078f630c50e291c56264cc0ff13d0c6cc"
integrity sha512-NZtbJOCbxKUFRFKMpamT38PUQMY0hX0p7TG5AEYOPhZKZEP7dHZ1K2s1aB8MdVH0qxmqX7nQleNrrvLf09Zfdw==
dependencies:
"@atproto-labs/pipe" "0.1.0"
"@atproto-labs/pipe" "0.1.1"
"@atproto-labs/pipe@0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@atproto-labs/pipe/-/pipe-0.1.0.tgz#c8d86923b6d8e900d39efe6fdcdf0d897c434086"
integrity sha512-ghOqHFyJlQVFPESzlVHjKroP0tPzbmG5Jms0dNI9yLDEfL8xp4OFPWLX4f6T8mRq69wWs4nIDM3sSsFbFqLa1w==
"@atproto-labs/pipe@0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@atproto-labs/pipe/-/pipe-0.1.1.tgz#1c4232d16bf95f251e993cb6ee440f9aa4e87ce6"
integrity sha512-hdNw2oUs2B6BN1lp+32pF7cp8EMKuIN5Qok2Vvv/aOpG/3tNSJ9YkvfI0k6Zd188LeDDYRUpYpxcoFIcGH/FNg==
"@atproto-labs/simple-store-memory@0.1.3":
version "0.1.3"
@@ -64,10 +63,10 @@
"@atproto/xrpc" "^0.7.0"
"@atproto/xrpc-server" "^0.7.18"
"@atproto/api@^0.15.7":
version "0.15.7"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.15.7.tgz#8436162d9fa5dac627bdd5c0f5c9598309ec1383"
integrity sha512-YRETLcOwDCYfGs7Sl9ObqPwhOlVWrPkw4f1AYGIrXLQS58WHe/vz1lZbqOqMsC6gvCnyZnOuKlhsRHZ14rBLzg==
"@atproto/api@^0.15.8":
version "0.15.8"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.15.8.tgz#f284a9c225191ebd35b46f5695932ab649c04a61"
integrity sha512-PsCgmV4zPjN8VuJMruxqauhn88PuS0b8t2Xsjl4617+bCPpY513jVlxgNH/XExxO7TSVvJM7EzdLY4o3fqh/xQ==
dependencies:
"@atproto/common-web" "^0.4.2"
"@atproto/lexicon" "^0.4.11"
@@ -95,14 +94,14 @@
multiformats "^9.9.0"
uint8arrays "3.0.0"
"@atproto/bsky@^0.0.149":
version "0.0.149"
resolved "https://registry.yarnpkg.com/@atproto/bsky/-/bsky-0.0.149.tgz#3e9cfb999b9958e9a61776eddb72d424905ec3be"
integrity sha512-7j2KgWHm1nOTQDmtEcNwtldTArS9WwZS3M+aw7OmGH8wCa8vEljNxP6HETjtktDMNTrSipHmmyqh25+Rc5+Ziw==
"@atproto/bsky@^0.0.150":
version "0.0.150"
resolved "https://registry.yarnpkg.com/@atproto/bsky/-/bsky-0.0.150.tgz#6626095875d805d0d3f38fa4e184b9f7d274c80f"
integrity sha512-dn1jzP1EId842+g78Q6EMdOmgEZxa9bSq20HMdd5/R8uu559mPs8zigFuddqCoT1fRaJXFC8ZP7Jk5asvBQhrA==
dependencies:
"@atproto-labs/fetch-node" "0.1.8"
"@atproto-labs/fetch-node" "0.1.9"
"@atproto-labs/xrpc-utils" "0.0.14"
"@atproto/api" "^0.15.7"
"@atproto/api" "^0.15.8"
"@atproto/common" "^0.4.11"
"@atproto/crypto" "^0.4.4"
"@atproto/did" "^0.1.5"
@@ -219,20 +218,20 @@
"@noble/hashes" "^1.6.1"
uint8arrays "3.0.0"
"@atproto/dev-env@^0.3.131":
version "0.3.131"
resolved "https://registry.yarnpkg.com/@atproto/dev-env/-/dev-env-0.3.131.tgz#b3b4cee5f367766d542515b1713523423ecb5a71"
integrity sha512-Tijqc/vq7qKGTpgoKm1BwyvP2QfoOQRjNm9Ro5CDAMXsKqHfXxPiytxYqxj6QR/PptC27aDUqgmexluZN6XbWg==
"@atproto/dev-env@^0.3.132":
version "0.3.132"
resolved "https://registry.yarnpkg.com/@atproto/dev-env/-/dev-env-0.3.132.tgz#78d55ef08a368a752c55b1ee7b7c08a41f27b5ac"
integrity sha512-RFd/9kgvmbP859N6NLu/FxCzLsj01iq22P9jNpL+dQNXbWXHYwGMUa6edf/ZrljNi3dFBNxabdDZJ2q+8uvBJQ==
dependencies:
"@atproto/api" "^0.15.7"
"@atproto/bsky" "^0.0.149"
"@atproto/api" "^0.15.8"
"@atproto/bsky" "^0.0.150"
"@atproto/bsync" "^0.0.19"
"@atproto/common-web" "^0.4.2"
"@atproto/crypto" "^0.4.4"
"@atproto/identity" "^0.4.8"
"@atproto/lexicon" "^0.4.11"
"@atproto/ozone" "^0.1.110"
"@atproto/pds" "^0.4.137"
"@atproto/ozone" "^0.1.111"
"@atproto/pds" "^0.4.138"
"@atproto/sync" "^0.1.23"
"@atproto/syntax" "^0.4.0"
"@atproto/xrpc-server" "^0.7.18"
@@ -302,21 +301,21 @@
optionalDependencies:
"@atproto/oauth-provider-api" "0.1.2"
"@atproto/oauth-provider-ui@0.1.4":
version "0.1.4"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-ui/-/oauth-provider-ui-0.1.4.tgz#5e092d30afa583fdab54fc78371aecb1cbfa017d"
integrity sha512-GTQnB7OUBFSeXcdRseAGYzKe9UUFB/kGjRcIA8+pO5pCMD7JdXI+WliUhsbdmQ2I+OK78aAlCrmygNWpLtpZgg==
"@atproto/oauth-provider-ui@0.1.5":
version "0.1.5"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-ui/-/oauth-provider-ui-0.1.5.tgz#b080c5e814975821689c5976c27ac1081211106f"
integrity sha512-pW0Vx3kvIWH1Mu3SOImNHP9JbmhSj2e3ChDvtfXCWI1oC03fiaMlJfdxrx9Plq5Z+DajnCzPzrf1Lvbopjf94Q==
optionalDependencies:
"@atproto/oauth-provider-api" "0.1.2"
"@atproto/oauth-provider@^0.7.6":
version "0.7.6"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider/-/oauth-provider-0.7.6.tgz#68bc37303611d548bae9f653d41bc89bd8890152"
integrity sha512-4YcnddACznmpuRmHlt9G+kccdv2Gct5qQOF9Yyjse8cl2Td+Rg1gkchpRdWUnyr9fgZzmCsSBYzEfVXge3eUiQ==
"@atproto/oauth-provider@^0.7.7":
version "0.7.7"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider/-/oauth-provider-0.7.7.tgz#dbbdeb405ab1d239fd926340f83fb41e13455011"
integrity sha512-ElphzmOjw1hr42HN4dD6sMAQFtpTkaJ8bBDAsbL9YBVJDEGhmHsF3Ye8mDUO4nhEdg7PUTWiCzXyqnaorAjiTA==
dependencies:
"@atproto-labs/fetch" "0.2.2"
"@atproto-labs/fetch-node" "0.1.8"
"@atproto-labs/pipe" "0.1.0"
"@atproto-labs/fetch" "0.2.3"
"@atproto-labs/fetch-node" "0.1.9"
"@atproto-labs/pipe" "0.1.1"
"@atproto-labs/simple-store" "0.2.0"
"@atproto-labs/simple-store-memory" "0.1.3"
"@atproto/common" "^0.4.11"
@@ -324,7 +323,7 @@
"@atproto/jwk-jose" "0.1.6"
"@atproto/oauth-provider-api" "0.1.2"
"@atproto/oauth-provider-frontend" "0.1.4"
"@atproto/oauth-provider-ui" "0.1.4"
"@atproto/oauth-provider-ui" "0.1.5"
"@atproto/oauth-types" "0.2.7"
"@atproto/syntax" "0.4.0"
"@hapi/accept" "^6.0.3"
@@ -337,7 +336,6 @@
http-errors "^2.0.0"
ioredis "^5.3.2"
jose "^5.2.0"
psl "^1.9.0"
zod "^3.23.8"
"@atproto/oauth-types@0.2.7":
@@ -348,12 +346,12 @@
"@atproto/jwk" "0.1.5"
zod "^3.23.8"
"@atproto/ozone@^0.1.110":
version "0.1.110"
resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.1.110.tgz#78ad57961b4699c8aa3e6f7d5b6f215d7760a723"
integrity sha512-X7VU7QAkwJrwpgmAuAHqvVDX9CEW0Ts5R4ovATgEt2lbxyxtJtYIm1dG346fAlOfC9f3RGN+HI8vBMWrrrLKAQ==
"@atproto/ozone@^0.1.111":
version "0.1.111"
resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.1.111.tgz#7ef4a02f1af045ab44254fb9d44ab0e50fd94ba9"
integrity sha512-NY+Cn/3dY4tPFkMUoJR1KMZN/v9ZIxjx6EQBMwn/nqTiHk0E3rtGEbyL2jLQ7x+FxpPTjDgpnn3K725+8XUaAg==
dependencies:
"@atproto/api" "^0.15.7"
"@atproto/api" "^0.15.8"
"@atproto/common" "^0.4.11"
"@atproto/crypto" "^0.4.4"
"@atproto/identity" "^0.4.8"
@@ -378,20 +376,20 @@
undici "^6.14.1"
ws "^8.12.0"
"@atproto/pds@^0.4.137":
version "0.4.137"
resolved "https://registry.yarnpkg.com/@atproto/pds/-/pds-0.4.137.tgz#87468703b02bf42681ddd50049ee906331655731"
integrity sha512-DRUck9CgOdK0cP6B6/1Cku2gb5t31Vhh9su2TcqF9eymZP1dNSI6nfTIEp+cuwpW/VpDeu7AfHCSgYfnJeZ5yg==
"@atproto/pds@^0.4.138":
version "0.4.138"
resolved "https://registry.yarnpkg.com/@atproto/pds/-/pds-0.4.138.tgz#437d785c83f710bf37bef8baf687b0a46ce9dc68"
integrity sha512-WLzDhmguTgs2wQNKoGxCbpKNegDnRiemSslenMbPrB7kSiXYj+XZobLyoIXHv1EnAd2pbThwNEL8z8EfkM0mDg==
dependencies:
"@atproto-labs/fetch-node" "0.1.8"
"@atproto-labs/fetch-node" "0.1.9"
"@atproto-labs/xrpc-utils" "0.0.14"
"@atproto/api" "^0.15.7"
"@atproto/api" "^0.15.8"
"@atproto/aws" "^0.2.21"
"@atproto/common" "^0.4.11"
"@atproto/crypto" "^0.4.4"
"@atproto/identity" "^0.4.8"
"@atproto/lexicon" "^0.4.11"
"@atproto/oauth-provider" "^0.7.6"
"@atproto/oauth-provider" "^0.7.7"
"@atproto/repo" "^0.8.1"
"@atproto/syntax" "^0.4.0"
"@atproto/xrpc" "^0.7.0"