phase 4 foundations: vendor missing lexicons, refreshSession api, toLex no-op purge, de-agent link-meta
This commit is contained in:
@@ -123,6 +123,10 @@
|
||||
"app.bsky.notification.unregisterPush",
|
||||
"app.bsky.notification.updateSeen",
|
||||
"app.bsky.richtext.facet",
|
||||
"app.bsky.unspecced.getSuggestedOnboardingUsers",
|
||||
"app.bsky.unspecced.getSuggestedUsersForDiscover",
|
||||
"app.bsky.unspecced.getSuggestedUsersForExplore",
|
||||
"app.bsky.unspecced.getSuggestedUsersForSeeMore",
|
||||
"app.bsky.video.defs",
|
||||
"app.bsky.video.getJobStatus",
|
||||
"app.bsky.video.getUploadLimits",
|
||||
@@ -273,6 +277,8 @@
|
||||
"com.atproto.sync.notifyOfUpdate",
|
||||
"com.atproto.sync.requestCrawl",
|
||||
"com.atproto.sync.subscribeRepos",
|
||||
"com.atproto.temp.checkHandleAvailability",
|
||||
"com.atproto.temp.checkSignupQueue",
|
||||
"com.germnetwork.declaration"
|
||||
],
|
||||
"resolutions": {
|
||||
@@ -800,6 +806,10 @@
|
||||
"uri": "at://did:plc:placeholder00000000000000000000/com.atproto.lexicon.schema/app.bsky.unspecced.getSuggestedFeedsSkeleton",
|
||||
"cid": "bafyreihqvsdre7oxhlpl7yucsmpdupwakipyzsu2gjlkbufgmklcgr5cbq"
|
||||
},
|
||||
"app.bsky.unspecced.getSuggestedOnboardingUsers": {
|
||||
"uri": "at://did:plc:placeholder00000000000000000000/com.atproto.lexicon.schema/app.bsky.unspecced.getSuggestedOnboardingUsers",
|
||||
"cid": "bafyreieot3hdk6h2enuivlp6m2jivd2y4npwbr4h7nsb3kutvnmtpkubm4"
|
||||
},
|
||||
"app.bsky.unspecced.getSuggestedStarterPacks": {
|
||||
"uri": "at://did:plc:placeholder00000000000000000000/com.atproto.lexicon.schema/app.bsky.unspecced.getSuggestedStarterPacks",
|
||||
"cid": "bafyreih34c76u3vbjaaukyojpsrljslmnptzpnydizyfrjtedzmwosmawy"
|
||||
@@ -812,6 +822,18 @@
|
||||
"uri": "at://did:plc:placeholder00000000000000000000/com.atproto.lexicon.schema/app.bsky.unspecced.getSuggestedUsers",
|
||||
"cid": "bafyreib5qavwbqignxipudnk5jzs2inlkjxosckpxakorbk3erlscfn6ba"
|
||||
},
|
||||
"app.bsky.unspecced.getSuggestedUsersForDiscover": {
|
||||
"uri": "at://did:plc:placeholder00000000000000000000/com.atproto.lexicon.schema/app.bsky.unspecced.getSuggestedUsersForDiscover",
|
||||
"cid": "bafyreienm4jci3ri5umqmdyycpyhtwjbteynqx54tyfjdrilzg6kqr65dm"
|
||||
},
|
||||
"app.bsky.unspecced.getSuggestedUsersForExplore": {
|
||||
"uri": "at://did:plc:placeholder00000000000000000000/com.atproto.lexicon.schema/app.bsky.unspecced.getSuggestedUsersForExplore",
|
||||
"cid": "bafyreidje2onbwlnhm6st54evtxvvsc5n3al4vxq67maah24a2hvwvsd2m"
|
||||
},
|
||||
"app.bsky.unspecced.getSuggestedUsersForSeeMore": {
|
||||
"uri": "at://did:plc:placeholder00000000000000000000/com.atproto.lexicon.schema/app.bsky.unspecced.getSuggestedUsersForSeeMore",
|
||||
"cid": "bafyreidg6zyy4x2cskf7jfdhlmn4nps6ug7tzqhckpx3s264xlxrh5djji"
|
||||
},
|
||||
"app.bsky.unspecced.getSuggestedUsersSkeleton": {
|
||||
"uri": "at://did:plc:placeholder00000000000000000000/com.atproto.lexicon.schema/app.bsky.unspecced.getSuggestedUsersSkeleton",
|
||||
"cid": "bafyreibvcocfbsxbf2s2rzuvcovkoyq6m7yz3csxrd6mdeoiwmkjqucxke"
|
||||
@@ -1456,6 +1478,14 @@
|
||||
"uri": "at://did:plc:6msi3pj7krzih5qxqtryxlzw/com.atproto.lexicon.schema/com.atproto.sync.subscribeRepos",
|
||||
"cid": "bafyreic6fm5atifiaq67u44dtxc3ufjbq3z7yysryjrzrw37hkb32yajbi"
|
||||
},
|
||||
"com.atproto.temp.checkHandleAvailability": {
|
||||
"uri": "at://did:plc:placeholder00000000000000000000/com.atproto.lexicon.schema/com.atproto.temp.checkHandleAvailability",
|
||||
"cid": "bafyreifanpe7ixmxampsbl3oaftbo24vzhe5pcunhf3xdsmrmgrgkq5ziq"
|
||||
},
|
||||
"com.atproto.temp.checkSignupQueue": {
|
||||
"uri": "at://did:plc:placeholder00000000000000000000/com.atproto.lexicon.schema/com.atproto.temp.checkSignupQueue",
|
||||
"cid": "bafyreignao6slhwqr5kqdiey243oy5wmewfkz4vzseoypdxzoyakwen7bm"
|
||||
},
|
||||
"com.germnetwork.declaration": {
|
||||
"uri": "at://did:plc:qyqmmncrm6qx33kpy7vqndik/com.atproto.lexicon.schema/com.germnetwork.declaration",
|
||||
"cid": "bafyreiekwjmxshje655olra4mata7npso7bbgytc4fop77ycjtrbewwi3y"
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "app.bsky.unspecced.getSuggestedOnboardingUsers",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "query",
|
||||
"description": "Get a list of suggested users for onboarding",
|
||||
"parameters": {
|
||||
"type": "params",
|
||||
"properties": {
|
||||
"category": {
|
||||
"type": "string",
|
||||
"description": "Category of users to get suggestions for."
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 50,
|
||||
"default": 25
|
||||
}
|
||||
}
|
||||
},
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["actors"],
|
||||
"properties": {
|
||||
"actors": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "ref",
|
||||
"ref": "app.bsky.actor.defs#profileView"
|
||||
}
|
||||
},
|
||||
"recId": {
|
||||
"type": "string",
|
||||
"description": "DEPRECATED: use recIdStr instead."
|
||||
},
|
||||
"recIdStr": {
|
||||
"type": "string",
|
||||
"description": "Snowflake for this recommendation, use when submitting recommendation events."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "app.bsky.unspecced.getSuggestedUsersForDiscover",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "query",
|
||||
"description": "Get a list of suggested users for the Discover page",
|
||||
"parameters": {
|
||||
"type": "params",
|
||||
"properties": {
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 50,
|
||||
"default": 25
|
||||
}
|
||||
}
|
||||
},
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["actors"],
|
||||
"properties": {
|
||||
"actors": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "ref",
|
||||
"ref": "app.bsky.actor.defs#profileView"
|
||||
}
|
||||
},
|
||||
"recIdStr": {
|
||||
"type": "string",
|
||||
"description": "Snowflake for this recommendation, use when submitting recommendation events."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "app.bsky.unspecced.getSuggestedUsersForDiscoverSkeleton",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "query",
|
||||
"description": "Get a skeleton of suggested users for the Discover page. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedUsersForDiscover",
|
||||
"parameters": {
|
||||
"type": "params",
|
||||
"properties": {
|
||||
"viewer": {
|
||||
"type": "string",
|
||||
"format": "did",
|
||||
"description": "DID of the account making the request (not included for public/unauthenticated queries)."
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 50,
|
||||
"default": 25
|
||||
}
|
||||
}
|
||||
},
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["dids"],
|
||||
"properties": {
|
||||
"dids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "did"
|
||||
}
|
||||
},
|
||||
"recIdStr": {
|
||||
"type": "string",
|
||||
"description": "Snowflake for this recommendation, use when submitting recommendation events."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "app.bsky.unspecced.getSuggestedUsersForExplore",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "query",
|
||||
"description": "Get a list of suggested users for the Explore page",
|
||||
"parameters": {
|
||||
"type": "params",
|
||||
"properties": {
|
||||
"category": {
|
||||
"type": "string",
|
||||
"description": "Category of users to get suggestions for."
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 50,
|
||||
"default": 25
|
||||
}
|
||||
}
|
||||
},
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["actors"],
|
||||
"properties": {
|
||||
"actors": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "ref",
|
||||
"ref": "app.bsky.actor.defs#profileView"
|
||||
}
|
||||
},
|
||||
"recIdStr": {
|
||||
"type": "string",
|
||||
"description": "Snowflake for this recommendation, use when submitting recommendation events."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "app.bsky.unspecced.getSuggestedUsersForExploreSkeleton",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "query",
|
||||
"description": "Get a skeleton of suggested users for the Explore page. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedUsersForExplore",
|
||||
"parameters": {
|
||||
"type": "params",
|
||||
"properties": {
|
||||
"viewer": {
|
||||
"type": "string",
|
||||
"format": "did",
|
||||
"description": "DID of the account making the request (not included for public/unauthenticated queries)."
|
||||
},
|
||||
"category": {
|
||||
"type": "string",
|
||||
"description": "Category of users to get suggestions for."
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 50,
|
||||
"default": 25
|
||||
}
|
||||
}
|
||||
},
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["dids"],
|
||||
"properties": {
|
||||
"dids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "did"
|
||||
}
|
||||
},
|
||||
"recIdStr": {
|
||||
"type": "string",
|
||||
"description": "Snowflake for this recommendation, use when submitting recommendation events."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "app.bsky.unspecced.getSuggestedUsersForSeeMore",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "query",
|
||||
"description": "Get a list of suggested users for the See More page",
|
||||
"parameters": {
|
||||
"type": "params",
|
||||
"properties": {
|
||||
"category": {
|
||||
"type": "string",
|
||||
"description": "Category of users to get suggestions for."
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 50,
|
||||
"default": 25
|
||||
}
|
||||
}
|
||||
},
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["actors"],
|
||||
"properties": {
|
||||
"actors": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "ref",
|
||||
"ref": "app.bsky.actor.defs#profileView"
|
||||
}
|
||||
},
|
||||
"recIdStr": {
|
||||
"type": "string",
|
||||
"description": "Snowflake for this recommendation, use when submitting recommendation events."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "app.bsky.unspecced.getSuggestedUsersForSeeMoreSkeleton",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "query",
|
||||
"description": "Get a skeleton of suggested users for the See More page. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedUsersForSeeMore",
|
||||
"parameters": {
|
||||
"type": "params",
|
||||
"properties": {
|
||||
"viewer": {
|
||||
"type": "string",
|
||||
"format": "did",
|
||||
"description": "DID of the account making the request (not included for public/unauthenticated queries)."
|
||||
},
|
||||
"category": {
|
||||
"type": "string",
|
||||
"description": "Category of users to get suggestions for."
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 50,
|
||||
"default": 25
|
||||
}
|
||||
}
|
||||
},
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["dids"],
|
||||
"properties": {
|
||||
"dids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "did"
|
||||
}
|
||||
},
|
||||
"recIdStr": {
|
||||
"type": "string",
|
||||
"description": "Snowflake for this recommendation, use when submitting recommendation events."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "com.atproto.temp.checkHandleAvailability",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "query",
|
||||
"description": "Checks whether the provided handle is available. If the handle is not available, available suggestions will be returned. Optional inputs will be used to generate suggestions.",
|
||||
"parameters": {
|
||||
"type": "params",
|
||||
"required": ["handle"],
|
||||
"properties": {
|
||||
"handle": {
|
||||
"type": "string",
|
||||
"format": "handle",
|
||||
"description": "Tentative handle. Will be checked for availability or used to build handle suggestions."
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "User-provided email. Might be used to build handle suggestions."
|
||||
},
|
||||
"birthDate": {
|
||||
"type": "string",
|
||||
"format": "datetime",
|
||||
"description": "User-provided birth date. Might be used to build handle suggestions."
|
||||
}
|
||||
}
|
||||
},
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["handle", "result"],
|
||||
"properties": {
|
||||
"handle": {
|
||||
"type": "string",
|
||||
"format": "handle",
|
||||
"description": "Echo of the input handle."
|
||||
},
|
||||
"result": {
|
||||
"type": "union",
|
||||
"refs": ["#resultAvailable", "#resultUnavailable"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"errors": [
|
||||
{
|
||||
"name": "InvalidEmail",
|
||||
"description": "An invalid email was provided."
|
||||
}
|
||||
]
|
||||
},
|
||||
"resultAvailable": {
|
||||
"type": "object",
|
||||
"description": "Indicates the provided handle is available.",
|
||||
"properties": {}
|
||||
},
|
||||
"resultUnavailable": {
|
||||
"type": "object",
|
||||
"description": "Indicates the provided handle is unavailable and gives suggestions of available handles.",
|
||||
"required": ["suggestions"],
|
||||
"properties": {
|
||||
"suggestions": {
|
||||
"type": "array",
|
||||
"description": "List of suggested handles based on the provided inputs.",
|
||||
"items": {
|
||||
"type": "ref",
|
||||
"ref": "#suggestion"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"suggestion": {
|
||||
"type": "object",
|
||||
"required": ["handle", "method"],
|
||||
"properties": {
|
||||
"handle": {
|
||||
"type": "string",
|
||||
"format": "handle"
|
||||
},
|
||||
"method": {
|
||||
"type": "string",
|
||||
"description": "Method used to build this suggestion. Should be considered opaque to clients. Can be used for metrics."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"lexicon": 1,
|
||||
"id": "com.atproto.temp.checkSignupQueue",
|
||||
"defs": {
|
||||
"main": {
|
||||
"type": "query",
|
||||
"description": "Check accounts location in signup queue.",
|
||||
"output": {
|
||||
"encoding": "application/json",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["activated"],
|
||||
"properties": {
|
||||
"activated": { "type": "boolean" },
|
||||
"placeInQueue": { "type": "integer" },
|
||||
"estimatedTimeMs": { "type": "integer" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,6 @@ export function useAutocomplete({
|
||||
key: profile.did,
|
||||
type: 'profile' as const,
|
||||
value: '@' + profile.handle,
|
||||
// TODO(phase4): drop toLex once searchActorsTypeahead (bridge agent)
|
||||
// emits #/lexicons views
|
||||
profile: toLex<AutocompleteProfile['profile']>(profile),
|
||||
}))
|
||||
@@ -134,10 +133,7 @@ function moderateProfileItem({
|
||||
item: AutocompleteProfile
|
||||
moderationOpts: ModerationOpts
|
||||
}) {
|
||||
// TODO(phase4): drop toLex once searchActorsTypeahead emits #/lexicons views
|
||||
const modui = moderateProfile(toLex(item.profile), moderationOpts).ui(
|
||||
'profileList',
|
||||
)
|
||||
const modui = moderateProfile(item.profile, moderationOpts).ui('profileList')
|
||||
const isExactMatch = query && item.profile.handle.toLowerCase() === query
|
||||
|
||||
if (
|
||||
|
||||
@@ -17,7 +17,6 @@ import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Person_Filled_Corner2_Rounded as PersonIcon} from '#/components/icons/Person'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
type Layout = {
|
||||
size: number
|
||||
@@ -163,10 +162,7 @@ function AvatarBubble({
|
||||
type="user"
|
||||
hideLiveBadge
|
||||
noBorder
|
||||
// TODO(phase4): drop toLex once profile props emit #/lexicons views
|
||||
moderation={moderateProfile(toLex(profile), moderationOpts).ui(
|
||||
'avatar',
|
||||
)}
|
||||
moderation={moderateProfile(profile, moderationOpts).ui('avatar')}
|
||||
/>
|
||||
) : (
|
||||
<AvatarPlaceholder size={size} />
|
||||
|
||||
@@ -7,7 +7,6 @@ import {useProfilesQuery} from '#/state/queries/profile'
|
||||
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
export function AvatarStack({
|
||||
profiles,
|
||||
@@ -35,8 +34,7 @@ export function AvatarStack({
|
||||
: profiles.map(item => ({
|
||||
key: item.did,
|
||||
profile: item,
|
||||
// TODO(phase4): drop toLex once useProfilesQuery emits #/lexicons views
|
||||
moderation: moderateProfile(toLex(item), moderationOpts),
|
||||
moderation: moderateProfile(item, moderationOpts),
|
||||
}))
|
||||
|
||||
return (
|
||||
|
||||
@@ -11,7 +11,6 @@ import {Link, type LinkProps} from '#/components/Link'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {type app} from '#/lexicons'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
const AVI_SIZE = 30
|
||||
const AVI_SIZE_SMALL = 20
|
||||
@@ -96,8 +95,7 @@ function KnownFollowersInner({
|
||||
const textStyle = [a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]
|
||||
|
||||
const slice = cachedKnownFollowers.followers.slice(0, 3).map(f => {
|
||||
// TODO(phase4): drop toLex once KnownFollowers emits #/lexicons views
|
||||
const moderation = moderateProfile(toLex(f), moderationOpts)
|
||||
const moderation = moderateProfile(f, moderationOpts)
|
||||
return {
|
||||
profile: {
|
||||
...f,
|
||||
|
||||
@@ -24,7 +24,6 @@ import * as Hider from '#/components/moderation/Hider'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {type app} from '#/lexicons'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
/*
|
||||
* This component is based on `FeedCard` and is tightly coupled with that
|
||||
@@ -55,8 +54,7 @@ export function Default(
|
||||
const {view, showPinButton} = props
|
||||
const moderationOpts = useModerationOpts()
|
||||
const moderation = moderationOpts
|
||||
? // TODO(phase4): drop toLex once ListView props emit #/lexicons views
|
||||
moderateUserList(toLex(view), moderationOpts)
|
||||
? moderateUserList(view, moderationOpts)
|
||||
: undefined
|
||||
|
||||
return (
|
||||
|
||||
@@ -20,7 +20,6 @@ import * as StarterPackCard from '#/components/StarterPack/StarterPackCard'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {IS_NATIVE} from '#/env'
|
||||
import {type app} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
export function NewskieDialog({
|
||||
profile,
|
||||
@@ -90,8 +89,7 @@ function DialogInner({
|
||||
|
||||
const profileName = useMemo(() => {
|
||||
if (!moderationOpts) return profile.displayName || profile.handle
|
||||
// TODO(phase4): drop toLex once ProfileViewDetailed prop emits #/lexicons views
|
||||
const moderation = moderateProfile(toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
return sanitizeDisplayName(
|
||||
profile.displayName || profile.handle,
|
||||
moderation.ui('displayName'),
|
||||
|
||||
@@ -5,7 +5,6 @@ import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import * as FeedCard from '#/components/FeedCard'
|
||||
import {ContentHider} from '#/components/moderation/ContentHider'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {type EmbedType} from '#/types/bsky/post'
|
||||
import {type CommonProps} from './types'
|
||||
|
||||
@@ -41,8 +40,7 @@ export function ModeratedFeedEmbed({
|
||||
const moderationOpts = useModerationOpts()
|
||||
const moderation = useMemo(() => {
|
||||
return moderationOpts
|
||||
? // TODO(phase4): drop toLex once feed embed view emits #/lexicons views
|
||||
moderateFeedGenerator(toLex(embed.view), moderationOpts)
|
||||
? moderateFeedGenerator(embed.view, moderationOpts)
|
||||
: undefined
|
||||
}, [embed.view, moderationOpts])
|
||||
return (
|
||||
|
||||
@@ -5,7 +5,6 @@ import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import * as ListCard from '#/components/ListCard'
|
||||
import {ContentHider} from '#/components/moderation/ContentHider'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {type EmbedType} from '#/types/bsky/post'
|
||||
import {type CommonProps} from './types'
|
||||
|
||||
@@ -31,8 +30,7 @@ export function ModeratedListEmbed({
|
||||
const moderationOpts = useModerationOpts()
|
||||
const moderation = useMemo(() => {
|
||||
return moderationOpts
|
||||
? // TODO(phase4): drop toLex once list embed view emits #/lexicons views
|
||||
moderateUserList(toLex(embed.view), moderationOpts)
|
||||
? moderateUserList(embed.view, moderationOpts)
|
||||
: undefined
|
||||
}, [embed.view, moderationOpts])
|
||||
return (
|
||||
|
||||
@@ -268,9 +268,7 @@ export function QuoteEmbed({
|
||||
[embed],
|
||||
)
|
||||
const moderation = useMemo(() => {
|
||||
return moderationOpts
|
||||
? moderatePost(bsky.toLex(quote), moderationOpts)
|
||||
: undefined
|
||||
return moderationOpts ? moderatePost(quote, moderationOpts) : undefined
|
||||
}, [quote, moderationOpts])
|
||||
|
||||
const t = useTheme()
|
||||
|
||||
@@ -22,7 +22,6 @@ import {ProfileBadges} from '#/components/ProfileBadges'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {type chat} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
export function RecentChats({
|
||||
postUri,
|
||||
@@ -121,8 +120,7 @@ function RecentChatItem({
|
||||
|
||||
const primaryProfile = useProfileShadow(primaryMember)
|
||||
|
||||
// TODO(phase4): drop toLex once useProfileShadow emits #/lexicons views
|
||||
const moderation = moderateProfile(toLex(primaryProfile), moderationOpts)
|
||||
const moderation = moderateProfile(primaryProfile, moderationOpts)
|
||||
const name =
|
||||
convo.kind === 'group'
|
||||
? convo.details.name
|
||||
|
||||
@@ -44,7 +44,7 @@ import * as Toast from '#/components/Toast'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {type Metrics} from '#/analytics'
|
||||
import {useActorStatus} from '#/features/liveNow'
|
||||
import * as bsky from '#/types/bsky'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
|
||||
export function Default({
|
||||
profile,
|
||||
@@ -170,7 +170,7 @@ export function Avatar({
|
||||
liveOverride?: boolean
|
||||
size?: number
|
||||
}) {
|
||||
const moderation = moderateProfile(bsky.toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
|
||||
const {isActive: live} = useActorStatus(profile)
|
||||
|
||||
@@ -240,7 +240,7 @@ function InlineNameAndHandle({
|
||||
moderationOpts: ModerationOpts
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const moderation = moderateProfile(bsky.toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
const name = sanitizeDisplayName(
|
||||
profile.displayName || sanitizeHandle(profile.handle),
|
||||
moderation.ui('displayName'),
|
||||
@@ -294,7 +294,7 @@ export function Name({
|
||||
style?: StyleProp<ViewStyle>
|
||||
textStyle?: StyleProp<TextStyle>
|
||||
}) {
|
||||
const moderation = moderateProfile(bsky.toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
const name = sanitizeDisplayName(
|
||||
profile.displayName || sanitizeHandle(profile.handle),
|
||||
moderation.ui('displayName'),
|
||||
@@ -479,7 +479,7 @@ export function FollowButtonInner({
|
||||
}: FollowButtonProps) {
|
||||
const {t: l} = useLingui()
|
||||
const profile = useProfileShadow(profileUnshadowed)
|
||||
const moderation = moderateProfile(bsky.toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(
|
||||
profile,
|
||||
logContext,
|
||||
@@ -617,7 +617,7 @@ export function Labels({
|
||||
profile: bsky.profile.AnyProfileView
|
||||
moderationOpts: ModerationOpts
|
||||
}) {
|
||||
const moderation = moderateProfile(bsky.toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
const modui = moderation.ui('profileList')
|
||||
const followedBy = profile.viewer?.followedBy
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ import {IS_WEB_TOUCH_DEVICE} from '#/env'
|
||||
import {useActorStatus} from '#/features/liveNow'
|
||||
import {LiveStatus} from '#/features/liveNow/components/LiveStatusDialog'
|
||||
import {type app} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {type ProfileHoverCardProps} from './types'
|
||||
|
||||
const floatingMiddlewares = [
|
||||
@@ -424,8 +423,7 @@ function Inner({
|
||||
const {_, i18n} = useLingui()
|
||||
const {currentAccount} = useSession()
|
||||
const moderation = useMemo(
|
||||
// TODO(phase4): drop toLex once ProfileViewDetailed prop emits #/lexicons views
|
||||
() => moderateProfile(toLex(profile), moderationOpts),
|
||||
() => moderateProfile(profile, moderationOpts),
|
||||
[profile, moderationOpts],
|
||||
)
|
||||
const [descriptionRT] = useRichText(profile.description ?? '')
|
||||
|
||||
@@ -26,7 +26,6 @@ import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {type app} from '#/lexicons'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
function WizardListCard({
|
||||
type,
|
||||
@@ -140,10 +139,7 @@ export function WizardProfileCard({
|
||||
const included = isTarget || state.profiles.some(p => p.did === profile.did)
|
||||
const disabled =
|
||||
isTarget || (!included && state.profiles.length >= STARTER_PACK_MAX_SIZE)
|
||||
// TODO(phase4): drop toLex once profile prop emits #/lexicons views
|
||||
const moderationUi = moderateProfile(toLex(profile), moderationOpts).ui(
|
||||
'avatar',
|
||||
)
|
||||
const moderationUi = moderateProfile(profile, moderationOpts).ui('avatar')
|
||||
const displayName = profile.displayName
|
||||
? sanitizeDisplayName(profile.displayName)
|
||||
: `@${sanitizeHandle(profile.handle)}`
|
||||
@@ -194,11 +190,9 @@ export function WizardFeedCard({
|
||||
const isDiscover = generator.uri === DISCOVER_FEED_URI
|
||||
const included = isDiscover || state.feeds.some(f => f.uri === generator.uri)
|
||||
const disabled = isDiscover || (!included && state.feeds.length >= 3)
|
||||
// TODO(phase4): drop toLex once GeneratorView prop emits #/lexicons views
|
||||
const moderationUi = moderateFeedGenerator(
|
||||
toLex(generator),
|
||||
moderationOpts,
|
||||
).ui('avatar')
|
||||
const moderationUi = moderateFeedGenerator(generator, moderationOpts).ui(
|
||||
'avatar',
|
||||
)
|
||||
|
||||
const onPress = () => {
|
||||
if (disabled) return
|
||||
|
||||
@@ -33,7 +33,6 @@ import * as ProfileCard from '#/components/ProfileCard'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {IS_WEB} from '#/env'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {AvatarBubbles} from '../AvatarBubbles'
|
||||
import {Error} from '../Error'
|
||||
import {ProfileBadges} from '../ProfileBadges'
|
||||
@@ -411,8 +410,7 @@ function DefaultProfileCard({
|
||||
const t = useTheme()
|
||||
const {t: l} = useLingui()
|
||||
const enabled = canBeMessaged(profile)
|
||||
// TODO(phase4): drop toLex once profile prop emits #/lexicons views
|
||||
const moderation = moderateProfile(toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
const handle = sanitizeHandle(profile.handle, '@')
|
||||
const displayName = createSanitizedDisplayName(
|
||||
profile,
|
||||
@@ -488,8 +486,7 @@ function ExistingChatCard({
|
||||
: createSanitizedDisplayName(
|
||||
convo.primaryMember,
|
||||
true,
|
||||
// TODO(phase4): drop toLex once convo primaryMember emits #/lexicons views
|
||||
moderateProfile(toLex(convo.primaryMember), moderationOpts).ui(
|
||||
moderateProfile(convo.primaryMember, moderationOpts).ui(
|
||||
'displayName',
|
||||
),
|
||||
)
|
||||
|
||||
@@ -28,7 +28,6 @@ import * as Toast from '#/components/Toast'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {IS_WEB} from '#/env'
|
||||
import {type app} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
const DISPLAY_NAME_MAX_GRAPHEMES = 64
|
||||
const DESCRIPTION_MAX_GRAPHEMES = 300
|
||||
@@ -165,9 +164,8 @@ function DialogInner({
|
||||
|
||||
// We want to be working with a blank state here, so let's get the
|
||||
// serialized version and turn it back into a RichText
|
||||
// TODO(phase4): drop toLex once the list view producer emits #/lexicons facets
|
||||
const serialized = richTextToString(
|
||||
new RichTextAPI({text, facets: toLex(facets)}),
|
||||
new RichTextAPI({text, facets: facets}),
|
||||
false,
|
||||
)
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Ti
|
||||
import * as ProfileCard from '#/components/ProfileCard'
|
||||
import {Text} from '#/components/Typography'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
type Props = {
|
||||
testID?: string
|
||||
@@ -90,8 +89,7 @@ function Tab({
|
||||
const {t: l} = useLingui()
|
||||
const moderationOpts = useModerationOpts()
|
||||
|
||||
// TODO(phase4): drop toLex once profile prop emits #/lexicons views
|
||||
const moderation = moderateProfile(toLex(profile), moderationOpts!)
|
||||
const moderation = moderateProfile(profile, moderationOpts!)
|
||||
const displayName = sanitizeDisplayName(
|
||||
profile.displayName || sanitizeHandle(profile.handle),
|
||||
moderation.ui('displayName'),
|
||||
|
||||
@@ -54,7 +54,6 @@ import {Text} from '#/components/Typography'
|
||||
import {useAgeAssurance} from '#/ageAssurance'
|
||||
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
type NewGroupChatItem = {
|
||||
type: 'newGroupChat'
|
||||
@@ -1071,8 +1070,7 @@ function DefaultProfileCard({
|
||||
const t = useTheme()
|
||||
const {t: l} = useLingui()
|
||||
const enabled = canBeMessaged(profile)
|
||||
// TODO(phase4): drop toLex once profile prop emits #/lexicons views
|
||||
const moderation = moderateProfile(toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
const handle = sanitizeHandle(profile.handle, '@')
|
||||
const displayName = sanitizeDisplayName(
|
||||
profile.displayName || sanitizeHandle(profile.handle),
|
||||
|
||||
@@ -29,7 +29,6 @@ import {useAnalytics} from '#/analytics'
|
||||
import {IS_NATIVE} from '#/env'
|
||||
import {type chat} from '#/lexicons'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {EmojiReactionPicker} from './EmojiReactionPicker'
|
||||
import {canReact, hasReachedReactionLimit} from './util'
|
||||
|
||||
@@ -87,8 +86,7 @@ export let MessageContextMenu = ({
|
||||
const str = richTextToString(
|
||||
new RichText({
|
||||
text: message.text,
|
||||
// TODO(phase4): drop toLex once the message producer emits #/lexicons facets
|
||||
facets: toLex(message.facets),
|
||||
facets: message.facets,
|
||||
}),
|
||||
true,
|
||||
)
|
||||
|
||||
@@ -344,9 +344,7 @@ let MessageItem = ({
|
||||
size={AVATAR_SIZE}
|
||||
type={profile.associated?.labeler ? 'labeler' : 'user'}
|
||||
onBeforePress={() => unstableCacheProfileView(queryClient, profile)}
|
||||
moderation={moderateProfile(bsky.toLex(profile), moderationOpts).ui(
|
||||
'avatar',
|
||||
)}
|
||||
moderation={moderateProfile(profile, moderationOpts).ui('avatar')}
|
||||
/>
|
||||
) : (
|
||||
<ProfileCard.AvatarPlaceholder size={AVATAR_SIZE} />
|
||||
|
||||
@@ -21,7 +21,6 @@ import {Link} from '#/components/Link'
|
||||
import {ProfileBadges} from '#/components/ProfileBadges'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {IS_LIQUID_GLASS} from '#/env'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {type ConvoWithDetails} from './util'
|
||||
|
||||
const PFP_SIZE = 40
|
||||
@@ -86,8 +85,7 @@ function ProfileHeaderReady({
|
||||
const {t: l} = useLingui()
|
||||
const profile = useProfileShadow(convo.primaryMember)
|
||||
|
||||
// TODO(phase4): drop toLex once useProfileShadow emits #/lexicons views
|
||||
const moderation = moderateProfile(toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
|
||||
const blockInfo = useMemo(() => {
|
||||
const modui = moderation.ui('profileView')
|
||||
|
||||
@@ -10,7 +10,6 @@ import * as Toggle from '#/components/forms/Toggle'
|
||||
import * as ProfileCard from '#/components/ProfileCard'
|
||||
import {Text} from '#/components/Typography'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
export function GroupChatProfileCard({
|
||||
profile,
|
||||
@@ -21,8 +20,7 @@ export function GroupChatProfileCard({
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const enabled = canBeAddedToGroup(profile)
|
||||
// TODO(phase4): drop toLex once profile prop emits #/lexicons views
|
||||
const moderation = moderateProfile(toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
const handle = sanitizeHandle(profile.handle, '@')
|
||||
const displayName = sanitizeDisplayName(
|
||||
profile.displayName || sanitizeHandle(profile.handle),
|
||||
|
||||
@@ -154,10 +154,7 @@ export function canReact({
|
||||
}
|
||||
|
||||
if (primaryMember && moderationOpts) {
|
||||
const moderation = moderateProfile(
|
||||
bsky.toLex(primaryMember),
|
||||
moderationOpts,
|
||||
)
|
||||
const moderation = moderateProfile(primaryMember, moderationOpts)
|
||||
if (convoState.convo.kind === 'direct') {
|
||||
// Either direction (blocking or blocked-by) hides reactions in 1-1s
|
||||
if (moderation.blocked) return false
|
||||
|
||||
@@ -395,11 +395,9 @@ function GroupChatJoinDialogContent({code}: {code?: string}) {
|
||||
{createSanitizedDisplayName(
|
||||
joinLinkPreview.owner,
|
||||
true,
|
||||
// TODO(phase4): drop toLex once join link preview emits #/lexicons views
|
||||
moderateProfile(
|
||||
bsky.toLex(joinLinkPreview.owner),
|
||||
moderationOpts,
|
||||
).ui('displayName'),
|
||||
moderateProfile(joinLinkPreview.owner, moderationOpts).ui(
|
||||
'displayName',
|
||||
),
|
||||
)}
|
||||
</InlineLinkText>
|
||||
</Trans>
|
||||
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
} from '#/components/moderation/LabelsOnMeDialog'
|
||||
import * as Pills from '#/components/Pills'
|
||||
import {type app, type com} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
export function PostAlerts({
|
||||
post,
|
||||
@@ -68,8 +67,7 @@ export function PostAlerts({
|
||||
*/
|
||||
const shownCauses = [...alerts, ...informs, ...modui.blurs]
|
||||
const additionalLabels = filterUserFacingLabels(
|
||||
// TODO(phase4): drop toLex once PostView labels are #/lexicons-typed
|
||||
toLex(allLabels),
|
||||
allLabels,
|
||||
currentAccount?.did,
|
||||
).filter(label =>
|
||||
shownCauses.every(
|
||||
|
||||
@@ -24,21 +24,7 @@ export function parseReportSubject(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(phase4): drop toLex once ReportSubject is a #/lexicons union. The view
|
||||
* subjects are structurally the #/lexicons shapes; we bridge here so the
|
||||
* `isType` schema guards below narrow against the lexicon `$type`s.
|
||||
*/
|
||||
const subject = bsky.toLex<
|
||||
| app.bsky.actor.defs.ProfileViewBasic
|
||||
| app.bsky.actor.defs.ProfileView
|
||||
| app.bsky.actor.defs.ProfileViewDetailed
|
||||
| app.bsky.actor.defs.StatusView
|
||||
| app.bsky.graph.defs.ListView
|
||||
| app.bsky.feed.defs.GeneratorView
|
||||
| app.bsky.graph.defs.StarterPackView
|
||||
| app.bsky.feed.defs.PostView
|
||||
>(rawSubject)
|
||||
const subject = rawSubject
|
||||
|
||||
if (
|
||||
bsky.isType(app.bsky.actor.defs.profileViewBasic, subject) ||
|
||||
|
||||
@@ -15,7 +15,6 @@ import {Loader} from '#/components/Loader'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {type app, com, tools} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
export function GoLiveDisabledDialog({
|
||||
control,
|
||||
@@ -60,7 +59,7 @@ export function DialogInner({
|
||||
} else {
|
||||
await pdsClient.call(
|
||||
com.atproto.moderation.createReport,
|
||||
toLex<com.atproto.moderation.createReport.$InputBody>({
|
||||
{
|
||||
reasonType: tools.ozone.report.defs.reasonAppeal.value,
|
||||
subject: {
|
||||
$type: 'com.atproto.repo.strongRef',
|
||||
@@ -68,7 +67,7 @@ export function DialogInner({
|
||||
cid: status.cid,
|
||||
},
|
||||
reason: details,
|
||||
}),
|
||||
},
|
||||
{
|
||||
service: api.moderation.service,
|
||||
},
|
||||
|
||||
@@ -27,7 +27,7 @@ import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {LiveIndicator} from '#/features/liveNow/components/LiveIndicator'
|
||||
import {type app} from '#/lexicons'
|
||||
import * as bsky from '#/types/bsky'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
|
||||
export function LiveStatusDialog({
|
||||
control,
|
||||
@@ -115,8 +115,7 @@ export function LiveStatus({
|
||||
const dialogContext = Dialog.useDialogContext()
|
||||
const moderation = useMemo(() => {
|
||||
if (!moderationOpts) return undefined
|
||||
// TODO(phase4): drop toLex once profile producers emit #/lexicons views
|
||||
return moderateStatus(bsky.toLex(profile), moderationOpts)
|
||||
return moderateStatus(profile, moderationOpts)
|
||||
}, [profile, moderationOpts])
|
||||
|
||||
return (
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
useMaybeProfileShadow,
|
||||
} from '#/state/cache/profile-shadow'
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {useAgent, usePdsClient, useSession} from '#/state/session'
|
||||
import {usePdsClient, useSession} from '#/state/session'
|
||||
import {useTickEveryMinute} from '#/state/shell'
|
||||
import {useDialogContext} from '#/components/Dialog'
|
||||
import * as Toast from '#/components/Toast'
|
||||
@@ -105,8 +105,7 @@ export function useActorStatus(actor?: bsky.profile.AnyProfileView) {
|
||||
const moderation = useMemo(() => {
|
||||
if (!actor || !('status' in actor && actor.status)) return undefined
|
||||
if (!moderationOpts) return undefined
|
||||
// TODO(phase4): drop toLex once profile producers emit #/lexicons views
|
||||
return moderateStatus(bsky.toLex(actor), moderationOpts)
|
||||
return moderateStatus(actor, moderationOpts)
|
||||
}, [actor, moderationOpts])
|
||||
|
||||
return useMemo(() => {
|
||||
@@ -120,12 +119,7 @@ export function useActorStatus(actor?: bsky.profile.AnyProfileView) {
|
||||
}
|
||||
|
||||
if (shadowed && 'status' in shadowed && shadowed.status) {
|
||||
/*
|
||||
* TODO(phase4): drop toLex once profile-shadow emits #/lexicons views.
|
||||
* The shadow store still holds old `@atproto/api` StatusViews, so brand
|
||||
* it once here to feed the new-world validation and returned view.
|
||||
*/
|
||||
const status = bsky.toLex<app.bsky.actor.defs.StatusView>(shadowed.status)
|
||||
const status = shadowed.status
|
||||
const isValid = isStatusValidForViewers(status, config)
|
||||
const isDisabled = status.isDisabled || false
|
||||
const isActive = isStatusStillActive(status.expiresAt)
|
||||
@@ -195,7 +189,6 @@ export function useLiveLinkMetaQuery(url: string | null) {
|
||||
const liveNowConfig = useLiveNowConfig()
|
||||
const {_} = useLingui()
|
||||
|
||||
const agent = useAgent()
|
||||
return useQuery({
|
||||
enabled: !!url,
|
||||
queryKey: ['link-meta', url],
|
||||
@@ -213,7 +206,7 @@ export function useLiveLinkMetaQuery(url: string | null) {
|
||||
)
|
||||
}
|
||||
|
||||
return await getLinkMeta(agent, url)
|
||||
return await getLinkMeta(url)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import {type Client} from '@atproto/lex-client'
|
||||
|
||||
import {DEMO_FEED} from '#/lib/demo'
|
||||
import {type app} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {type FeedAPI, type FeedAPIResponse} from './types'
|
||||
|
||||
export class DemoFeedAPI implements FeedAPI {
|
||||
@@ -12,17 +11,13 @@ export class DemoFeedAPI implements FeedAPI {
|
||||
this.client = client
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
async peekLatest(): Promise<app.bsky.feed.defs.FeedViewPost> {
|
||||
/*
|
||||
* TODO(phase4): drop this cast once `#/lib/demo` (DEMO_FEED) sources its
|
||||
* feed items from `#/lexicons`. Its records are still typed against the old
|
||||
* `@atproto/api` FeedViewPost, which does not assign to the branded lexicon
|
||||
* type this method must return.
|
||||
*/
|
||||
return toLex(DEMO_FEED.feed[0])
|
||||
return DEMO_FEED.feed[0]
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
async fetch(): Promise<FeedAPIResponse> {
|
||||
return toLex(DEMO_FEED)
|
||||
return DEMO_FEED
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import {feedUriToHref} from '#/lib/strings/url-helpers'
|
||||
import {getContentLanguages} from '#/state/preferences/languages'
|
||||
import {type FeedParams} from '#/state/queries/post-feed'
|
||||
import {app} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {FeedTuner} from '../feed-manip'
|
||||
import {type FeedTunerFn} from '../feed-manip'
|
||||
import {
|
||||
@@ -264,13 +263,7 @@ class MergeFeedSource_Following extends MergeFeedSource {
|
||||
return {
|
||||
success: true,
|
||||
cursor: res.cursor,
|
||||
/*
|
||||
* TODO(phase4): drop the toLex once `#/lib/api/feed-manip` (FeedTuner)
|
||||
* flips its FeedViewPost source from `@atproto/api` to `#/lexicons`. Its
|
||||
* `_feedPost` is still the old-world view type, which does not assign to
|
||||
* the branded lexicon type this page carries.
|
||||
*/
|
||||
feed: slices.map(slice => toLex(slice._feedPost)),
|
||||
feed: slices.map(slice => slice._feedPost),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-35
@@ -91,16 +91,7 @@ export async function post(
|
||||
for (let i = 0; i < thread.posts.length; i++) {
|
||||
const draft = thread.posts[i]
|
||||
|
||||
/*
|
||||
* Not awaited to avoid waterfalls. `draft.richtext` is still an
|
||||
* `@atproto/api` RichText (composer state is migrated by Task 7); the SDK
|
||||
* RichText is structurally the same transplant, so bridge it here.
|
||||
* TODO(phase4): drop toLex once composer state migrates to SDK RichText.
|
||||
*/
|
||||
const rtPromise = resolveRT(
|
||||
resolveClients.appview,
|
||||
bsky.toLex<RichText>(draft.richtext),
|
||||
)
|
||||
const rtPromise = resolveRT(resolveClients.appview, draft.richtext)
|
||||
const embedPromise = resolveEmbed(
|
||||
clients,
|
||||
queryClient,
|
||||
@@ -138,17 +129,11 @@ export async function post(
|
||||
langs,
|
||||
labels,
|
||||
}
|
||||
/*
|
||||
* `value` is typed `LexMap` (a loose index-signature map). A generated
|
||||
* record type is a valid LexMap at runtime but a strict interface is not
|
||||
* assignable to an index-signature type, so widen with `toLex` at this
|
||||
* boundary. Not a brand cast - the record is already fully typed.
|
||||
*/
|
||||
writes.push({
|
||||
$type: 'com.atproto.repo.applyWrites#create',
|
||||
collection: 'app.bsky.feed.post',
|
||||
rkey: rkey,
|
||||
value: bsky.toLex(record),
|
||||
value: record,
|
||||
})
|
||||
|
||||
if (i === 0 && thread.threadgate.some(tg => tg.type !== 'everybody')) {
|
||||
@@ -156,14 +141,10 @@ export async function post(
|
||||
$type: 'com.atproto.repo.applyWrites#create',
|
||||
collection: 'app.bsky.feed.threadgate',
|
||||
rkey: rkey,
|
||||
value: bsky.toLex(
|
||||
createThreadgateRecord({
|
||||
post: uri,
|
||||
allow: threadgateAllowUISettingToAllowRecordValue(
|
||||
thread.threadgate,
|
||||
),
|
||||
}),
|
||||
),
|
||||
value: createThreadgateRecord({
|
||||
post: uri,
|
||||
allow: threadgateAllowUISettingToAllowRecordValue(thread.threadgate),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -175,12 +156,12 @@ export async function post(
|
||||
$type: 'com.atproto.repo.applyWrites#create',
|
||||
collection: 'app.bsky.feed.postgate',
|
||||
rkey: rkey,
|
||||
value: bsky.toLex({
|
||||
value: {
|
||||
...thread.postgate,
|
||||
$type: 'app.bsky.feed.postgate',
|
||||
createdAt: now.toISOString(),
|
||||
post: uri,
|
||||
}),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -426,7 +407,7 @@ async function resolveMedia(
|
||||
* structural shape matches the lexicon blob field; the CID hasher handles
|
||||
* both class instances and plain lex blobs (see computeCid).
|
||||
*/
|
||||
video: bsky.toLex(videoDraft.pendingPublish.blobRef),
|
||||
video: videoDraft.pendingPublish.blobRef,
|
||||
alt: videoDraft.altText || undefined,
|
||||
captions: captions.length === 0 ? undefined : captions,
|
||||
aspectRatio,
|
||||
@@ -475,13 +456,7 @@ async function resolveMedia(
|
||||
title: resolvedLink.title,
|
||||
description: resolvedLink.description,
|
||||
thumb: blob,
|
||||
/*
|
||||
* associatedRefs comes from getLinkMeta, still typed with the old
|
||||
* `@atproto/api` StrongRef (link-meta.ts is out of scope). The shape
|
||||
* is identical; bridge with toLex.
|
||||
* TODO(phase4): drop toLex once link-meta migrates.
|
||||
*/
|
||||
associatedRefs: bsky.toLex(resolvedLink.associatedRefs),
|
||||
associatedRefs: resolvedLink.associatedRefs,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
+3
-15
@@ -23,7 +23,6 @@ import {
|
||||
import {type ComposerImage} from '#/state/gallery'
|
||||
import {createComposerImage} from '#/state/gallery'
|
||||
import {type ChatInvitePreview} from '#/state/queries/join-links'
|
||||
import {type SessionAgent} from '#/state/session'
|
||||
import {type Gif} from '#/features/gifPicker/types'
|
||||
import {app, chat, com} from '#/lexicons'
|
||||
import {createGIFDescription} from '../gif-alt-text'
|
||||
@@ -31,13 +30,10 @@ import {createGIFDescription} from '../gif-alt-text'
|
||||
/**
|
||||
* Clients the link resolver needs. `appview` serves the `app.bsky.*` feed/graph
|
||||
* reads plus handle resolution; `chat` serves the group join-link previews.
|
||||
* `agent` is still threaded through to {@link getLinkMeta}, which has not yet
|
||||
* migrated off the bridge - it only reads the (unused) service URL from it.
|
||||
*/
|
||||
export type ResolveClients = {
|
||||
appview: Client
|
||||
chat: Client
|
||||
agent: SessionAgent
|
||||
}
|
||||
|
||||
type ResolvedExternalLink = {
|
||||
@@ -195,7 +191,7 @@ export async function resolveLink(
|
||||
view: res.starterPack,
|
||||
}
|
||||
}
|
||||
return resolveExternal(clients, uri)
|
||||
return resolveExternal(uri)
|
||||
|
||||
// Forked from useGetPost. TODO: move into RQ.
|
||||
async function getPost({uri}: {uri: string}) {
|
||||
@@ -267,16 +263,8 @@ function getFileSlug(url: string | undefined): string | undefined {
|
||||
return dotIndex > 0 ? filename.slice(0, dotIndex) : undefined
|
||||
}
|
||||
|
||||
async function resolveExternal(
|
||||
clients: ResolveClients,
|
||||
uri: string,
|
||||
): Promise<ResolvedExternalLink> {
|
||||
/*
|
||||
* getLinkMeta still takes the bridge agent (not yet migrated); it only reads
|
||||
* a service URL from it that LINK_META_PROXY ignores. Keep threading the
|
||||
* agent here until link-meta migrates.
|
||||
*/
|
||||
const result = await getLinkMeta(clients.agent, uri)
|
||||
async function resolveExternal(uri: string): Promise<ResolvedExternalLink> {
|
||||
const result = await getLinkMeta(uri)
|
||||
return {
|
||||
type: 'external',
|
||||
uri: result.url,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {LINK_META_PROXY} from '#/lib/constants'
|
||||
import {getGiphyMetaUri} from '#/lib/strings/embed-player'
|
||||
import {parseStarterPackUri} from '#/lib/strings/starter-pack'
|
||||
import {type SessionAgent} from '#/state/session'
|
||||
import {type app} from '#/lexicons'
|
||||
import {isBskyAppUrl} from '../strings/url-helpers'
|
||||
|
||||
@@ -31,7 +30,6 @@ export interface LinkMeta {
|
||||
}
|
||||
|
||||
export async function getLinkMeta(
|
||||
agent: SessionAgent,
|
||||
url: string,
|
||||
timeout = 15e3,
|
||||
): Promise<LinkMeta> {
|
||||
@@ -80,9 +78,7 @@ export async function getLinkMeta(
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${LINK_META_PROXY(agent.serviceUrl.toString() || '')}${encodeURIComponent(
|
||||
url,
|
||||
)}`,
|
||||
`${LINK_META_PROXY('')}${encodeURIComponent(url)}`,
|
||||
{signal: controller.signal},
|
||||
)
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
} from '#/lib/moderation/useGlobalLabelStrings'
|
||||
import {useLabelDefinitions} from '#/state/preferences'
|
||||
import {type app, type com} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
export interface LabelInfo {
|
||||
label: com.atproto.label.defs.Label
|
||||
@@ -23,26 +22,14 @@ export interface LabelInfo {
|
||||
|
||||
export function useLabelInfo(label: com.atproto.label.defs.Label): LabelInfo {
|
||||
const {i18n} = useLingui()
|
||||
/*
|
||||
* TODO(phase4): drop the `toLex` casts once `useLabelDefinitions`
|
||||
* (state/preferences/label-defs) emits `#/lexicons` / `@bsky.app/sdk`
|
||||
* moderation types. It still returns old `@atproto/api`
|
||||
* `InterpretedLabelValueDefinition` / `LabelerViewDetailed`, which are
|
||||
* structurally identical to the SDK/lexicon ones modulo branded strings.
|
||||
*/
|
||||
const {labelDefs, labelers} = useLabelDefinitions()
|
||||
const def = getDefinition(
|
||||
toLex<Record<string, InterpretedLabelValueDefinition[]>>(labelDefs),
|
||||
label,
|
||||
)
|
||||
const def = getDefinition(labelDefs, label)
|
||||
const globalLabelStrings = useGlobalLabelStrings()
|
||||
return {
|
||||
label,
|
||||
def,
|
||||
strings: getLabelStrings(i18n.locale, globalLabelStrings, def),
|
||||
labeler: toLex<app.bsky.labeler.defs.LabelerViewDetailed[]>(labelers).find(
|
||||
labeler => label.src === labeler.creator.did,
|
||||
),
|
||||
labeler: labelers.find(labeler => label.src === labeler.creator.did),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ import {type Props as SVGIconProps} from '#/components/icons/common'
|
||||
import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash'
|
||||
import {Warning_Stroke2_Corner0_Rounded as Warning} from '#/components/icons/Warning'
|
||||
import {type AppModerationCause} from '#/components/Pills'
|
||||
import {type com} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {useGlobalLabelStrings} from './useGlobalLabelStrings'
|
||||
import {getDefinition, getLabelStrings} from './useLabelInfo'
|
||||
|
||||
@@ -129,18 +127,7 @@ export function useModerationCauseDescription(
|
||||
}
|
||||
}
|
||||
if (cause.type === 'label') {
|
||||
/*
|
||||
* TODO(phase4): drop `toLex` once `useLabelDefinitions` and the label
|
||||
* cause type share the `#/lexicons` label shape. `labelDefs` still comes
|
||||
* from the old `@atproto/api`-typed producer and `cause.label` is the SDK
|
||||
* label; both are structurally identical to the `#/lexicons` label.
|
||||
*/
|
||||
const def =
|
||||
cause.labelDef ||
|
||||
getDefinition(
|
||||
toLex<Parameters<typeof getDefinition>[0]>(labelDefs),
|
||||
toLex<com.atproto.label.defs.Label>(cause.label),
|
||||
)
|
||||
const def = cause.labelDef || getDefinition(labelDefs, cause.label)
|
||||
const strings = getLabelStrings(i18n.locale, globalLabelStrings, def)
|
||||
const labeler = labelers.find(l => l.creator.did === cause.label.src)
|
||||
let source = labeler
|
||||
|
||||
@@ -46,7 +46,7 @@ import {Error} from '#/components/Error'
|
||||
import * as Layout from '#/components/Layout'
|
||||
import {IS_LIQUID_GLASS} from '#/env'
|
||||
import {chat} from '#/lexicons'
|
||||
import {isType, toLex} from '#/types/bsky'
|
||||
import {isType} from '#/types/bsky'
|
||||
import {ChatDisabled} from './components/ChatDisabled'
|
||||
import {ChatEnded} from './components/ChatEnded'
|
||||
import {ChatLocked} from './components/ChatLocked'
|
||||
@@ -228,8 +228,7 @@ function InnerReady({
|
||||
const moderationOpts = useModerationOpts()
|
||||
const primaryMemberModeration = useMemo(() => {
|
||||
if (!primaryMember || !moderationOpts) return null
|
||||
// TODO(phase4): drop toLex once useMaybeProfileShadow emits #/lexicons views
|
||||
return moderateProfile(toLex(primaryMember), moderationOpts)
|
||||
return moderateProfile(primaryMember, moderationOpts)
|
||||
}, [primaryMember, moderationOpts])
|
||||
|
||||
const header = <MessagesListHeader convo={convo} />
|
||||
|
||||
@@ -21,7 +21,6 @@ import * as ProfileCard from '#/components/ProfileCard'
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {MemberMenu} from './MemberMenu'
|
||||
import {RemoveMemberPrompt} from './prompts'
|
||||
import {StatusBadge} from './StatusBadge'
|
||||
@@ -81,8 +80,7 @@ export function Member({
|
||||
return <MemberPlaceholder />
|
||||
}
|
||||
|
||||
// TODO(phase4): drop toLex once useProfileShadow emits #/lexicons views
|
||||
const moderation = moderateProfile(toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
|
||||
const isDeletedAccount = profile.handle === 'missing.invalid'
|
||||
const displayName = isDeletedAccount
|
||||
@@ -108,13 +106,10 @@ export function Member({
|
||||
}
|
||||
|
||||
const joinedReason = profile.kind?.addedBy
|
||||
? // TODO(phase4): drop toLex once addedBy emits #/lexicons views
|
||||
l`Added by ${createSanitizedDisplayName(
|
||||
? l`Added by ${createSanitizedDisplayName(
|
||||
profile.kind.addedBy,
|
||||
true,
|
||||
moderateProfile(toLex(profile.kind.addedBy), moderationOpts).ui(
|
||||
'displayName',
|
||||
),
|
||||
moderateProfile(profile.kind.addedBy, moderationOpts).ui('displayName'),
|
||||
)}`
|
||||
: l`Added by invite link`
|
||||
|
||||
|
||||
@@ -187,9 +187,8 @@ export function JoinRequest({setScreenState}: Props) {
|
||||
{createSanitizedDisplayName(
|
||||
joinLinkPreview.owner,
|
||||
true,
|
||||
// TODO(phase4): drop toLex once join link preview emits #/lexicons views
|
||||
moderateProfile(
|
||||
bsky.toLex(joinLinkPreview.owner),
|
||||
joinLinkPreview.owner,
|
||||
moderationOpts,
|
||||
).ui('displayName'),
|
||||
)}
|
||||
@@ -224,14 +223,12 @@ export function JoinRequest({setScreenState}: Props) {
|
||||
? l`Sign in to request access to this group chat.`
|
||||
: l`Sign in to accept invite.`}{' '}
|
||||
{joinLinkPreview.joinRule === 'followedByOwner' &&
|
||||
// TODO(phase4): drop toLex once join link preview emits #/lexicons views
|
||||
l`Only people ${createSanitizedDisplayName(
|
||||
joinLinkPreview.owner,
|
||||
true,
|
||||
moderateProfile(
|
||||
bsky.toLex(joinLinkPreview.owner),
|
||||
moderationOpts,
|
||||
).ui('displayName'),
|
||||
moderateProfile(joinLinkPreview.owner, moderationOpts).ui(
|
||||
'displayName',
|
||||
),
|
||||
)} follows can join.`}
|
||||
</Text>
|
||||
<ActionButtons setScreenState={setScreenState} />
|
||||
|
||||
@@ -125,8 +125,7 @@ function DirectChatItem({
|
||||
const {isWithinLeftPanel} = useIsWithinSplitView()
|
||||
|
||||
const moderation = useMemo(
|
||||
// TODO(phase4): drop toLex once useProfileShadow emits #/lexicons views
|
||||
() => moderateProfile(bsky.toLex(profile), moderationOpts),
|
||||
() => moderateProfile(profile, moderationOpts),
|
||||
[profile, moderationOpts],
|
||||
)
|
||||
|
||||
@@ -193,10 +192,7 @@ function GroupChatItem({
|
||||
|
||||
const moderation = useMemo(
|
||||
() =>
|
||||
groupOwner
|
||||
? // TODO(phase4): drop toLex once useMaybeProfileShadow emits #/lexicons views
|
||||
moderateProfile(bsky.toLex(groupOwner), moderationOpts)
|
||||
: undefined,
|
||||
groupOwner ? moderateProfile(groupOwner, moderationOpts) : undefined,
|
||||
[groupOwner, moderationOpts],
|
||||
)
|
||||
|
||||
@@ -423,15 +419,7 @@ function BaseChatItem({
|
||||
for (const member of convo.view.members) {
|
||||
unstableCacheProfileView(queryClient, member)
|
||||
}
|
||||
/*
|
||||
* `convo.view` comes from the still-old-typed `#/components/dms/util`
|
||||
* (migrates in a later task) while the convo cache is now keyed on the
|
||||
* lexicon ConvoView. TODO(phase4): drop toLex once dms/util migrates.
|
||||
*/
|
||||
precacheConvoQuery(
|
||||
queryClient,
|
||||
bsky.toLex<chat.bsky.convo.defs.ConvoView>(convo.view),
|
||||
)
|
||||
precacheConvoQuery(queryClient, convo.view)
|
||||
void decrementBadgeCount(convo.view.unreadCount)
|
||||
if (isDeletedAccount) {
|
||||
e.preventDefault()
|
||||
@@ -525,10 +513,7 @@ function BaseChatItem({
|
||||
}
|
||||
onPressIn={() =>
|
||||
// see onPress: old-typed dms/util view into the new-typed cache
|
||||
precacheConvoQuery(
|
||||
queryClient,
|
||||
bsky.toLex<chat.bsky.convo.defs.ConvoView>(convo.view),
|
||||
)
|
||||
precacheConvoQuery(queryClient, convo.view)
|
||||
}
|
||||
onPress={onPress}
|
||||
onLongPress={showMenu && IS_NATIVE ? onLongPress : undefined}
|
||||
|
||||
@@ -17,7 +17,6 @@ import {ProfileBadges} from '#/components/ProfileBadges'
|
||||
import {usePromptControl} from '#/components/Prompt'
|
||||
import {Text} from '#/components/Typography'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {AcceptChatButton, DeleteChatButton, RejectMenu} from './RequestButtons'
|
||||
|
||||
export function ChatStatusInfo({convoState}: {convoState: ActiveConvoStates}) {
|
||||
@@ -115,8 +114,7 @@ function InviterHeader({
|
||||
const t = useTheme()
|
||||
const profile = useProfileShadow(profileUnshadowed)
|
||||
const moderation = useMemo(
|
||||
// TODO(phase4): drop toLex once useProfileShadow emits #/lexicons views
|
||||
() => moderateProfile(toLex(profile), moderationOpts),
|
||||
() => moderateProfile(profile, moderationOpts),
|
||||
[profile, moderationOpts],
|
||||
)
|
||||
const displayName = createSanitizedDisplayName(
|
||||
|
||||
@@ -34,7 +34,6 @@ import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_WEB} from '#/env'
|
||||
import {type chat} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {CopyTextButton} from './CopyTextButton'
|
||||
import {EditTextButton} from './EditTextButton'
|
||||
|
||||
@@ -69,8 +68,7 @@ export function InviteLinkDialog({
|
||||
const ownerName = createSanitizedDisplayName(
|
||||
owner,
|
||||
false,
|
||||
// TODO(phase4): drop toLex once GroupConvoMember emits #/lexicons views
|
||||
moderateProfile(toLex(owner), moderationOpts).ui('displayName'),
|
||||
moderateProfile(owner, moderationOpts).ui('displayName'),
|
||||
)
|
||||
|
||||
const {joinLink} = convo.details
|
||||
|
||||
@@ -38,7 +38,6 @@ import {Loader} from '#/components/Loader'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {IS_ANDROID, IS_IOS, IS_LIQUID_GLASS, IS_NATIVE, IS_WEB} from '#/env'
|
||||
import {type chat} from '#/lexicons'
|
||||
import * as bsky from '#/types/bsky'
|
||||
import {type MessageEmbedState} from './MessageInputEmbed'
|
||||
|
||||
const MIN_HEIGHT = 40
|
||||
@@ -70,15 +69,7 @@ export function MessageComposer({
|
||||
const {getDraft, clearDraft} = useMessageDraft()
|
||||
const composerInternalApiRef = useComposerInternalApiRef()
|
||||
const {replyTo: replyToOld, clearReply} = useMessageReplies()
|
||||
/*
|
||||
* `useMessageReplies` (`#/components/dms`, migrates in a later task) still
|
||||
* emits the old `@atproto/api` MessageView; the send path is typed on the
|
||||
* lexicon view. Structurally identical modulo branded strings.
|
||||
* TODO(phase4): drop toLex once dms/MessageReplies migrates.
|
||||
*/
|
||||
const replyTo = bsky.toLex<chat.bsky.convo.defs.MessageView | null>(
|
||||
replyToOld,
|
||||
)
|
||||
const replyTo = replyToOld
|
||||
|
||||
const [text, setText] = useState(getDraft)
|
||||
useSaveMessageDraft(text)
|
||||
|
||||
@@ -569,24 +569,18 @@ export function MessagesList({
|
||||
try {
|
||||
const post = await getPost({uri: embedState.uri})
|
||||
if (post) {
|
||||
/*
|
||||
* `post` comes from the still-old-typed `useGetPost` producer
|
||||
* (migrates in a later task), so its uri/view shapes carry plain
|
||||
* strings where the lexicon types are branded. TODO(phase4): drop
|
||||
* toLex once that producer migrates.
|
||||
*/
|
||||
embed = bsky.toLex<$Typed<app.bsky.embed.record.Main>>({
|
||||
embed = {
|
||||
$type: 'app.bsky.embed.record',
|
||||
record: {
|
||||
uri: post.uri,
|
||||
cid: post.cid,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
embedView = bsky.toLex<$Typed<app.bsky.embed.record.View>>({
|
||||
embedView = {
|
||||
$type: 'app.bsky.embed.record#view',
|
||||
record: createEmbedViewRecordFromPost(post),
|
||||
})
|
||||
}
|
||||
|
||||
stripLinkFacet(uri => {
|
||||
if (!isBskyPostUrl(uri)) return false
|
||||
@@ -611,14 +605,10 @@ export function MessagesList({
|
||||
|
||||
const joinLinkPreview = await getJoinLinkPreview({code, hasSession})
|
||||
if (joinLinkPreview) {
|
||||
/*
|
||||
* The preview comes from the still-old-typed `join-links.ts` query
|
||||
* (migrates in a later task). TODO(phase4): drop toLex once it does.
|
||||
*/
|
||||
embedView = bsky.toLex<$Typed<chat.bsky.embed.joinLink.View>>({
|
||||
embedView = {
|
||||
$type: 'chat.bsky.embed.joinLink#view',
|
||||
joinLinkPreview,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
stripLinkFacet(uri => getChatInviteCodeFromUrl(uri) === code)
|
||||
|
||||
@@ -16,7 +16,6 @@ import {Person_Stroke2_Corner2_Rounded as PersonIcon} from '#/components/icons/P
|
||||
import {ProfileBadges} from '#/components/ProfileBadges'
|
||||
import * as ProfileCard from '#/components/ProfileCard'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
export function MessagesListInfoPanel({
|
||||
convo,
|
||||
@@ -35,11 +34,10 @@ export function MessagesListInfoPanel({
|
||||
)[0]
|
||||
const handle = sanitizeHandle(profile.handle, '@')
|
||||
const displayName = moderationOpts
|
||||
? // TODO(phase4): drop toLex once convo members emit #/lexicons views
|
||||
createSanitizedDisplayName(
|
||||
? createSanitizedDisplayName(
|
||||
profile,
|
||||
true,
|
||||
moderateProfile(toLex(profile), moderationOpts).ui('displayName'),
|
||||
moderateProfile(profile, moderationOpts).ui('displayName'),
|
||||
)
|
||||
: handle
|
||||
const profileLink =
|
||||
|
||||
@@ -41,7 +41,6 @@ import * as Menu from '#/components/Menu'
|
||||
import {ReportDialog} from '#/components/moderation/ReportDialog'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {type chat} from '#/lexicons'
|
||||
import * as bsky from '#/types/bsky'
|
||||
|
||||
export function RejectMenu({
|
||||
convo,
|
||||
@@ -229,18 +228,10 @@ export function AcceptChatButton({
|
||||
onMutate: () => {
|
||||
onAcceptConvo?.()
|
||||
if (currentScreen === 'list') {
|
||||
/*
|
||||
* `convo` is the old-typed view threaded from `#/components/dms/util`
|
||||
* consumers while the convo cache is now keyed on the lexicon
|
||||
* ConvoView. TODO(phase4): drop toLex once this file's props flip.
|
||||
*/
|
||||
precacheConvoQuery(
|
||||
queryClient,
|
||||
bsky.toLex<chat.bsky.convo.defs.ConvoView>({
|
||||
...convo,
|
||||
status: 'accepted',
|
||||
}),
|
||||
)
|
||||
precacheConvoQuery(queryClient, {
|
||||
...convo,
|
||||
status: 'accepted',
|
||||
})
|
||||
navigation.navigate('MessagesConversation', {
|
||||
conversation: convo.id,
|
||||
accept: true,
|
||||
|
||||
@@ -16,7 +16,6 @@ import {ProfileHoverCard} from '#/components/ProfileHoverCard'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {type app} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
const AVI_SIZE = 20
|
||||
|
||||
@@ -94,8 +93,7 @@ export function KnownLikers({post}: {post: AppBskyFeedDefs.PostView}) {
|
||||
.map(like => like.actor)
|
||||
.map(actor => ({
|
||||
actor,
|
||||
// TODO(phase4): drop toLex once useLikedBySampleQuery emits #/lexicons views
|
||||
moderation: moderateProfile(toLex(actor), moderationOpts),
|
||||
moderation: moderateProfile(actor, moderationOpts),
|
||||
}))
|
||||
.filter(({actor, moderation}) => {
|
||||
const modui = moderation.ui('profileList')
|
||||
|
||||
@@ -33,7 +33,6 @@ import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_IOS} from '#/env'
|
||||
import {type app} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {ProfileHeaderDisplayName} from './DisplayName'
|
||||
import {EditProfileDialog} from './EditProfileDialog'
|
||||
import {ProfileHeaderHandle} from './Handle'
|
||||
@@ -67,7 +66,7 @@ let ProfileHeaderLabeler = ({
|
||||
const isSelf = currentAccount?.did === profile.did
|
||||
|
||||
const moderation = useMemo(
|
||||
() => moderateProfile(toLex(profile), moderationOpts),
|
||||
() => moderateProfile(profile, moderationOpts),
|
||||
[profile, moderationOpts],
|
||||
)
|
||||
const {mutateAsync: likeMod, isPending: isLikePending} = useLikeMutation()
|
||||
|
||||
@@ -40,7 +40,6 @@ import {IS_IOS, IS_NATIVE} from '#/env'
|
||||
import {InviteFriendsDialog} from '#/features/inviteFriends'
|
||||
import {useActorStatus} from '#/features/liveNow'
|
||||
import {type app} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {GermButton} from '../components/GermButton'
|
||||
import {ProfileHeaderDisplayName} from './DisplayName'
|
||||
import {EditProfileDialog} from './EditProfileDialog'
|
||||
@@ -69,7 +68,7 @@ let ProfileHeaderStandard = ({
|
||||
const {currentAccount} = useSession()
|
||||
const {_} = useLingui()
|
||||
const moderation = useMemo(
|
||||
() => moderateProfile(toLex(profile), moderationOpts),
|
||||
() => moderateProfile(profile, moderationOpts),
|
||||
[profile, moderationOpts],
|
||||
)
|
||||
const [, queueUnblock] = useProfileBlockMutationQueue(profile)
|
||||
|
||||
@@ -22,7 +22,6 @@ import {Header} from '#/components/Layout'
|
||||
import * as ProfileCard from '#/components/ProfileCard'
|
||||
import {IS_NATIVE} from '#/env'
|
||||
import {type app} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {
|
||||
HeaderLabelerButtons,
|
||||
ProfileHeaderLabeler,
|
||||
@@ -112,8 +111,7 @@ const MinimalHeader = memo(function MinimalHeader({
|
||||
const profile = useProfileShadow(profileUnshadowed)
|
||||
const moderationOpts = useModerationOpts()
|
||||
const moderation = useMemo(
|
||||
() =>
|
||||
moderationOpts ? moderateProfile(toLex(profile), moderationOpts) : null,
|
||||
() => (moderationOpts ? moderateProfile(profile, moderationOpts) : null),
|
||||
[moderationOpts, profile],
|
||||
)
|
||||
const [visible, setVisible] = useState(false)
|
||||
|
||||
@@ -24,7 +24,6 @@ import {RichText} from '#/components/RichText'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {type app} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {MoreOptionsMenu} from './MoreOptionsMenu'
|
||||
import {SubscribeMenu} from './SubscribeMenu'
|
||||
|
||||
@@ -130,8 +129,7 @@ export function Header({
|
||||
list.description
|
||||
? new RichTextAPI({
|
||||
text: list.description,
|
||||
// TODO(phase4): drop toLex once the list view producer emits #/lexicons facets
|
||||
facets: toLex(list.descriptionFacets),
|
||||
facets: list.descriptionFacets,
|
||||
})
|
||||
: undefined,
|
||||
[list],
|
||||
|
||||
@@ -39,7 +39,6 @@ import {Loader} from '#/components/Loader'
|
||||
import * as Hider from '#/components/moderation/Hider'
|
||||
import {IS_WEB} from '#/env'
|
||||
import {type app} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
import {AboutSection} from './AboutSection'
|
||||
import {ErrorScreen} from './components/ErrorScreen'
|
||||
import {Header} from './components/Header'
|
||||
@@ -167,8 +166,7 @@ function ProfileListScreenLoaded({
|
||||
const [headerHeight, setHeaderHeight] = useState<number | null>(null)
|
||||
|
||||
const moderation = useMemo(() => {
|
||||
// TODO(phase4): drop toLex once ListView prop emits #/lexicons views
|
||||
return moderateUserList(toLex(list), moderationOpts)
|
||||
return moderateUserList(list, moderationOpts)
|
||||
}, [list, moderationOpts])
|
||||
|
||||
useSetTitle(isHidden ? _(msg`List Hidden`) : list.name)
|
||||
|
||||
@@ -22,7 +22,6 @@ import {ProfileBadges} from '#/components/ProfileBadges'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
export function SearchHistory({
|
||||
searchHistory,
|
||||
@@ -207,8 +206,7 @@ function RecentProfileItem({
|
||||
const {t: l} = useLingui()
|
||||
const width = 80
|
||||
|
||||
// TODO(phase4): drop toLex once profile prop emits #/lexicons views
|
||||
const moderation = moderateProfile(toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
const name = sanitizeDisplayName(
|
||||
profile.displayName || sanitizeHandle(profile.handle),
|
||||
moderation.ui('displayName'),
|
||||
|
||||
@@ -29,7 +29,6 @@ import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {type app} from '#/lexicons'
|
||||
import * as ModuleHeader from '../components/ModuleHeader'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
const IMAGE_SIZE = 56
|
||||
|
||||
@@ -307,8 +306,7 @@ function useModerateTrendingActors(
|
||||
|
||||
return actors
|
||||
.filter(actor => {
|
||||
// TODO(phase4): drop toLex once TrendView actors emit #/lexicons views
|
||||
const decision = moderateProfile(toLex(actor), moderationOpts)
|
||||
const decision = moderateProfile(actor, moderationOpts)
|
||||
return !decision.ui('avatar').filter && !decision.ui('avatar').blur
|
||||
})
|
||||
.slice(0, 3)
|
||||
|
||||
@@ -70,7 +70,6 @@ import {useActorStatus} from '#/features/liveNow'
|
||||
import {type app} from '#/lexicons'
|
||||
import {device, useStorage} from '#/storage'
|
||||
import {useActivitySubscriptionsNudged} from '#/storage/hooks/activity-subscriptions-nudged'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'>
|
||||
export function SettingsScreen({}: Props) {
|
||||
@@ -331,8 +330,7 @@ function ProfilePreview({
|
||||
|
||||
if (!moderationOpts) return null
|
||||
|
||||
// TODO(phase4): drop toLex once ProfileViewDetailed prop emits #/lexicons views
|
||||
const moderation = moderateProfile(toLex(profile), moderationOpts)
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
const displayName = sanitizeDisplayName(
|
||||
profile.displayName || sanitizeHandle(profile.handle),
|
||||
moderation.ui('displayName'),
|
||||
@@ -639,10 +637,7 @@ function AccountRow({
|
||||
<UserAvatar
|
||||
size={28}
|
||||
avatar={profile.avatar}
|
||||
// TODO(phase4): drop toLex once ProfileViewDetailed prop emits #/lexicons views
|
||||
moderation={moderateProfile(toLex(profile), moderationOpts).ui(
|
||||
'avatar',
|
||||
)}
|
||||
moderation={moderateProfile(profile, moderationOpts).ui('avatar')}
|
||||
type={profile.associated?.labeler ? 'labeler' : 'user'}
|
||||
live={live}
|
||||
hideLiveBadge
|
||||
|
||||
@@ -411,8 +411,7 @@ function Header({
|
||||
const richText = record.description
|
||||
? new RichTextAPI({
|
||||
text: record.description,
|
||||
// TODO(phase4): drop toLex once the starterpack record producer emits #/lexicons facets
|
||||
facets: bsky.toLex(record.descriptionFacets),
|
||||
facets: record.descriptionFacets,
|
||||
})
|
||||
: undefined
|
||||
|
||||
|
||||
@@ -808,8 +808,7 @@ function Overlay({
|
||||
: undefined
|
||||
const richText = new RichTextAPI({
|
||||
text: record?.text || '',
|
||||
// TODO(phase4): drop toLex once the post record producer emits #/lexicons facets
|
||||
facets: bsky.toLex(record?.facets),
|
||||
facets: record?.facets,
|
||||
})
|
||||
const handle = sanitizeHandle(post.author.handle, '@')
|
||||
|
||||
|
||||
@@ -205,12 +205,8 @@ export function useFeedPreviews(
|
||||
if (item.isFallbackMarker) continue
|
||||
|
||||
const moderations = item.items.map(item =>
|
||||
// TODO(phase4): drop toLex once feed-manip is migrated off
|
||||
// @atproto/api and yields lex-typed slice items.
|
||||
moderatePost(
|
||||
bsky.toLex<app.bsky.feed.defs.PostView>(item.post),
|
||||
moderationOpts!,
|
||||
),
|
||||
moderatePost(item.post, moderationOpts!),
|
||||
)
|
||||
|
||||
// apply moderation filters
|
||||
@@ -236,19 +232,12 @@ export function useFeedPreviews(
|
||||
const feedPostSliceItem: FeedPostSliceItem = {
|
||||
_reactKey: `${item._reactKey}-${i}-${subItem.post.uri}`,
|
||||
uri: subItem.post.uri,
|
||||
// TODO(phase4): drop toLex once feed-manip is migrated
|
||||
// off @atproto/api and yields lex-typed slice items.
|
||||
post: bsky.toLex<app.bsky.feed.defs.PostView>(
|
||||
subItem.post,
|
||||
),
|
||||
record: bsky.toLex<app.bsky.feed.post.Main>(
|
||||
subItem.record,
|
||||
),
|
||||
post: subItem.post,
|
||||
record: subItem.record,
|
||||
moderation: moderations[i],
|
||||
parentAuthor: subItem.parentAuthor
|
||||
? bsky.toLex<app.bsky.actor.defs.ProfileViewBasic>(
|
||||
subItem.parentAuthor,
|
||||
)
|
||||
? subItem.parentAuthor
|
||||
: undefined,
|
||||
isParentBlocked: subItem.isParentBlocked,
|
||||
isParentNotFound: subItem.isParentNotFound,
|
||||
|
||||
@@ -57,33 +57,24 @@ export function useAddGroupMembers(
|
||||
chat.bsky.actor.defs.ProfileViewBasic[]
|
||||
>(listConvoMembersQueryKey(convoId))
|
||||
|
||||
/*
|
||||
* The profile views come from producers that still emit the old
|
||||
* `@atproto/api` shapes (useProfileQuery migrates in a later task), while
|
||||
* the chat caches are now typed on the lexicon views. Structurally
|
||||
* identical modulo branded strings. TODO(phase4): drop toLex once those
|
||||
* producers migrate.
|
||||
*/
|
||||
const addedBy: chat.bsky.actor.defs.ProfileViewBasic | undefined =
|
||||
myProfile
|
||||
? bsky.toLex<chat.bsky.actor.defs.ProfileViewBasic>({
|
||||
? {
|
||||
...myProfile,
|
||||
$type: 'chat.bsky.actor.defs#profileViewBasic',
|
||||
})
|
||||
}
|
||||
: undefined
|
||||
|
||||
const optimisticMembers: chat.bsky.actor.defs.ProfileViewBasic[] =
|
||||
profiles.map(profile =>
|
||||
bsky.toLex<chat.bsky.actor.defs.ProfileViewBasic>({
|
||||
...profile,
|
||||
$type: 'chat.bsky.actor.defs#profileViewBasic',
|
||||
kind: {
|
||||
$type: 'chat.bsky.actor.defs#groupConvoMember',
|
||||
role: 'standard',
|
||||
addedBy,
|
||||
},
|
||||
}),
|
||||
)
|
||||
profiles.map(profile => ({
|
||||
...profile,
|
||||
$type: 'chat.bsky.actor.defs#profileViewBasic',
|
||||
kind: {
|
||||
$type: 'chat.bsky.actor.defs#groupConvoMember',
|
||||
role: 'standard',
|
||||
addedBy,
|
||||
},
|
||||
}))
|
||||
|
||||
queryClient.setQueryData<chat.bsky.convo.defs.ConvoView>(
|
||||
CONVO_KEY(convoId),
|
||||
|
||||
@@ -297,11 +297,8 @@ export function* findAllPostsInQueryData(
|
||||
if (bsky.isType(app.bsky.feed.defs.postView, item.subject)) {
|
||||
const quotedPost = getEmbeddedPost(item.subject?.embed)
|
||||
if (quotedPost && didOrHandleUriMatches(atUri, quotedPost)) {
|
||||
// TODO(phase4): drop toLex once ../util is migrated and
|
||||
// embedViewRecordToPostView returns the lexicon PostView.
|
||||
yield bsky.toLex<app.bsky.feed.defs.PostView>(
|
||||
embedViewRecordToPostView(quotedPost),
|
||||
)
|
||||
yield embedViewRecordToPostView(quotedPost)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,9 +288,8 @@ export function usePostFeedQuery(
|
||||
.map(slice => {
|
||||
const moderations = slice.items.map(item =>
|
||||
moderatePost(
|
||||
// TODO(phase4): drop toLex once feed-manip is migrated
|
||||
// off @atproto/api and yields lex-typed slice items.
|
||||
bsky.toLex<app.bsky.feed.defs.PostView>(item.post),
|
||||
item.post,
|
||||
moderationOpts!,
|
||||
),
|
||||
)
|
||||
@@ -342,19 +341,12 @@ export function usePostFeedQuery(
|
||||
const feedPostSliceItem: FeedPostSliceItem = {
|
||||
_reactKey: `${slice._reactKey}-${i}-${item.post.uri}`,
|
||||
uri: item.post.uri,
|
||||
// TODO(phase4): drop toLex once feed-manip is migrated
|
||||
// off @atproto/api and yields lex-typed slice items.
|
||||
post: bsky.toLex<app.bsky.feed.defs.PostView>(
|
||||
item.post,
|
||||
),
|
||||
record: bsky.toLex<app.bsky.feed.post.Main>(
|
||||
item.record,
|
||||
),
|
||||
post: item.post,
|
||||
record: item.record,
|
||||
moderation: moderations[i],
|
||||
parentAuthor: item.parentAuthor
|
||||
? bsky.toLex<app.bsky.actor.defs.ProfileViewBasic>(
|
||||
item.parentAuthor,
|
||||
)
|
||||
? item.parentAuthor
|
||||
: undefined,
|
||||
isParentBlocked: item.isParentBlocked,
|
||||
isParentNotFound: item.isParentNotFound,
|
||||
|
||||
@@ -44,7 +44,6 @@ import {useAgeAssurance} from '#/ageAssurance'
|
||||
import {makeAgeRestrictedModerationPrefs} from '#/ageAssurance/util'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {app} from '#/lexicons'
|
||||
import {toLex} from '#/types/bsky'
|
||||
|
||||
export * from '#/state/queries/preferences/const'
|
||||
export * from '#/state/queries/preferences/moderation'
|
||||
@@ -110,16 +109,8 @@ export function usePreferencesQuery() {
|
||||
) {
|
||||
data = {
|
||||
...data,
|
||||
/*
|
||||
* TODO(phase4): drop the toLex bridges once
|
||||
* `#/ageAssurance/util` (makeAgeRestrictedModerationPrefs) sources
|
||||
* `ModerationPrefs` from `@bsky.app/sdk/moderation` instead of
|
||||
* `@atproto/api`. The two shapes differ only in scalar branding
|
||||
* (e.g. MutedWord.actorTarget's UnknownString), so the values are
|
||||
* structurally interchangeable at this boundary.
|
||||
*/
|
||||
moderationPrefs: toLex(
|
||||
makeAgeRestrictedModerationPrefs(toLex(data.moderationPrefs)),
|
||||
moderationPrefs: makeAgeRestrictedModerationPrefs(
|
||||
data.moderationPrefs,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
resolveLink,
|
||||
} from '#/lib/api/resolve'
|
||||
import {STALE} from '#/state/queries/index'
|
||||
import {useAgent, useChatClient, useLexClient} from '#/state/session'
|
||||
import {useChatClient, useLexClient} from '#/state/session'
|
||||
import {type Gif} from '#/features/gifPicker/types'
|
||||
|
||||
export const RQKEY_LINK_ROOT = 'resolve-link'
|
||||
@@ -26,15 +26,13 @@ export function resolveLinkQueryOptions(clients: ResolveClients, url: string) {
|
||||
|
||||
/**
|
||||
* Bundle the clients the link resolver needs from the session hooks. The
|
||||
* appview client serves the `app.bsky.*` reads and handle resolution, the chat
|
||||
* client serves group join-link previews, and the bridge agent is still passed
|
||||
* through to the not-yet-migrated `getLinkMeta`.
|
||||
* appview client serves the `app.bsky.*` reads and handle resolution, and the
|
||||
* chat client serves group join-link previews.
|
||||
*/
|
||||
export function useResolveClients(): ResolveClients {
|
||||
const appview = useLexClient()
|
||||
const chat = useChatClient()
|
||||
const agent = useAgent()
|
||||
return {appview, chat, agent}
|
||||
return {appview, chat}
|
||||
}
|
||||
|
||||
export function useResolveLinkQuery(url: string) {
|
||||
|
||||
@@ -255,27 +255,23 @@ export function* getThreadPlaceholderCandidates(
|
||||
for (let post of findAllPostsInNotifsQueryData(queryClient, uri)) {
|
||||
yield postViewToThreadPlaceholder(post)
|
||||
}
|
||||
/*
|
||||
* TODO(phase4): drop toLex once the feed/quote/search/bookmarks/explore
|
||||
* `findAllPostsInQueryData` generators are migrated to `#/lexicons` types.
|
||||
*/
|
||||
for (let post of findAllPostsInFeedQueryData(queryClient, uri)) {
|
||||
yield postViewToThreadPlaceholder(bsky.toLex(post))
|
||||
yield postViewToThreadPlaceholder(post)
|
||||
}
|
||||
for (let post of findAllPostsInQuoteQueryData(queryClient, uri)) {
|
||||
yield postViewToThreadPlaceholder(bsky.toLex(post))
|
||||
yield postViewToThreadPlaceholder(post)
|
||||
}
|
||||
for (let post of findAllPostsInSearchQueryData(queryClient, uri)) {
|
||||
yield postViewToThreadPlaceholder(bsky.toLex(post))
|
||||
yield postViewToThreadPlaceholder(post)
|
||||
}
|
||||
for (let post of findAllPostsInBookmarksQueryData(queryClient, uri)) {
|
||||
yield postViewToThreadPlaceholder(bsky.toLex(post))
|
||||
yield postViewToThreadPlaceholder(post)
|
||||
}
|
||||
for (let post of findAllPostsInExploreFeedPreviewsQueryData(
|
||||
queryClient,
|
||||
uri,
|
||||
)) {
|
||||
yield postViewToThreadPlaceholder(bsky.toLex(post))
|
||||
yield postViewToThreadPlaceholder(post)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,11 +298,7 @@ export function* findAllPostsInQueryData(
|
||||
|
||||
const qp = getEmbeddedPost(item.value.post.embed)
|
||||
if (qp && didOrHandleUriMatches(atUri, qp)) {
|
||||
/*
|
||||
* TODO(phase4): drop toLex once `embedViewRecordToPostView` in
|
||||
* `#/state/queries/util` is migrated to `#/lexicons` types.
|
||||
*/
|
||||
yield bsky.toLex(embedViewRecordToPostView(qp))
|
||||
yield embedViewRecordToPostView(qp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -335,11 +327,7 @@ export function* findAllProfilesInQueryData(
|
||||
|
||||
const qp = getEmbeddedPost(item.value.post.embed)
|
||||
if (qp && qp.author.did === did) {
|
||||
/*
|
||||
* TODO(phase4): drop toLex once `getEmbeddedPost` in
|
||||
* `#/state/queries/util` is migrated to `#/lexicons` types.
|
||||
*/
|
||||
yield bsky.toLex(qp.author)
|
||||
yield qp.author
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ const ApiContext = createContext<SessionApiContext>({
|
||||
resumeSession: async () => {},
|
||||
removeAccount: () => {},
|
||||
partialRefreshSession: async () => {},
|
||||
refreshSession: () => Promise.resolve(undefined),
|
||||
})
|
||||
ApiContext.displayName = 'SessionApiContext'
|
||||
|
||||
@@ -344,6 +345,28 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
})
|
||||
}, [store, state, cancelPendingTask])
|
||||
|
||||
const refreshSession = useCallback<
|
||||
SessionApiContext['refreshSession']
|
||||
>(async () => {
|
||||
const bundle = store.getState().currentAgentState.agent as unknown as
|
||||
| SessionBundle
|
||||
| PublicSessionBundle
|
||||
if (!bundle.session) return undefined // logged out: nothing to refresh
|
||||
/*
|
||||
* PasswordSession.refresh() re-runs com.atproto.server.refreshSession +
|
||||
* getSession. On success the session's onUpdated hook fires, which the
|
||||
* armed makeSessionHooks wiring maps to an 'update' event; the reducer
|
||||
* snapshots the refreshed account. No explicit dispatch is needed here.
|
||||
* The returned snapshot lets callers read post-refresh fields without
|
||||
* waiting on the (async) reducer update.
|
||||
*/
|
||||
await bundle.session.refresh()
|
||||
return sessionDataToSessionAccount(
|
||||
bundle.session.session,
|
||||
bundle.session.session.service,
|
||||
)
|
||||
}, [store])
|
||||
|
||||
const removeAccount = useCallback<SessionApiContext['removeAccount']>(
|
||||
account => {
|
||||
addSessionDebugLog({
|
||||
@@ -443,6 +466,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
resumeSession,
|
||||
removeAccount,
|
||||
partialRefreshSession,
|
||||
refreshSession,
|
||||
}),
|
||||
[
|
||||
createAccount,
|
||||
@@ -452,6 +476,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
resumeSession,
|
||||
removeAccount,
|
||||
partialRefreshSession,
|
||||
refreshSession,
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -51,4 +51,15 @@ export type SessionApiContext = {
|
||||
* `persistSessionHandler`.
|
||||
*/
|
||||
partialRefreshSession: () => Promise<void>
|
||||
/**
|
||||
* Force a full session refresh (re-runs `com.atproto.server.refreshSession`
|
||||
* plus `getSession`) and return the refreshed account snapshot, or
|
||||
* `undefined` when logged out.
|
||||
*
|
||||
* The refresh routes through the session's own `refresh()`, whose success
|
||||
* hook propagates the updated account into state; the returned snapshot lets
|
||||
* callers read post-refresh fields synchronously without waiting on the
|
||||
* (async) reducer update. Rejections propagate to the caller.
|
||||
*/
|
||||
refreshSession: () => Promise<SessionAccount | undefined>
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import {mimeToExt} from '#/lib/media/video/util'
|
||||
import {shortenLinks} from '#/lib/strings/rich-text-manip'
|
||||
import {type ComposerImage} from '#/state/gallery'
|
||||
import {threadgateAllowUISettingToAllowRecordValue} from '#/state/queries/threadgate/util'
|
||||
import {createPublicAgent} from '#/state/session/agent'
|
||||
import {getPublicLexClient} from '#/state/session/clients'
|
||||
import {
|
||||
type ComposerState,
|
||||
@@ -141,10 +140,9 @@ async function postDraftToServerPost(
|
||||
|
||||
// Add quote record embed
|
||||
if (post.embed.quote) {
|
||||
const agent = createPublicAgent()
|
||||
const publicClient = getPublicLexClient()
|
||||
const resolved = await resolveLink(
|
||||
{appview: publicClient, chat: publicClient, agent},
|
||||
{appview: publicClient, chat: publicClient},
|
||||
post.embed.quote.uri,
|
||||
)
|
||||
if (resolved && resolved.type === 'record') {
|
||||
|
||||
@@ -148,15 +148,12 @@ let NotificationFeedItem = ({
|
||||
{
|
||||
profile: item.notification.author,
|
||||
href: makeProfileLink(item.notification.author),
|
||||
moderation: moderateProfile(
|
||||
bsky.toLex(item.notification.author),
|
||||
moderationOpts,
|
||||
),
|
||||
moderation: moderateProfile(item.notification.author, moderationOpts),
|
||||
},
|
||||
...(item.additional?.map(({author}) => ({
|
||||
profile: author,
|
||||
href: makeProfileLink(author),
|
||||
moderation: moderateProfile(bsky.toLex(author), moderationOpts),
|
||||
moderation: moderateProfile(author, moderationOpts),
|
||||
})) || []),
|
||||
].filter(
|
||||
(author, index, arr) =>
|
||||
|
||||
@@ -73,8 +73,7 @@ export function PostQuotes({uri}: {uri: string}) {
|
||||
) {
|
||||
return null
|
||||
}
|
||||
// TODO(phase4): drop toLex once usePostQuotesQuery emits #/lexicons views
|
||||
const moderation = moderatePost(bsky.toLex(post), moderationOpts)
|
||||
const moderation = moderatePost(post, moderationOpts)
|
||||
return {post, record: post.record, moderation}
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -61,17 +61,13 @@ export function Post({
|
||||
record
|
||||
? new RichTextAPI({
|
||||
text: record.text,
|
||||
// TODO(phase4): drop toLex once the post record producer emits #/lexicons facets
|
||||
facets: bsky.toLex(record.facets),
|
||||
facets: record.facets,
|
||||
})
|
||||
: undefined,
|
||||
[record],
|
||||
)
|
||||
const moderation = useMemo(
|
||||
() =>
|
||||
moderationOpts
|
||||
? moderatePost(bsky.toLex(post), moderationOpts)
|
||||
: undefined,
|
||||
() => (moderationOpts ? moderatePost(post, moderationOpts) : undefined),
|
||||
[moderationOpts, post],
|
||||
)
|
||||
if (postShadowed === POST_TOMBSTONE) {
|
||||
@@ -135,8 +131,7 @@ function PostInner({
|
||||
text: record.text,
|
||||
author: post.author,
|
||||
embed: post.embed,
|
||||
// TODO(phase4): drop toLex once the composer state accepts SDK ModerationDecision
|
||||
moderation: bsky.toLex(moderation),
|
||||
moderation: moderation,
|
||||
langs: record.langs,
|
||||
},
|
||||
logContext: 'PostReply',
|
||||
|
||||
@@ -99,8 +99,7 @@ export function PostFeedItem({
|
||||
() =>
|
||||
new RichTextAPI({
|
||||
text: record.text,
|
||||
// TODO(phase4): drop toLex once the post record producer emits #/lexicons facets
|
||||
facets: bsky.toLex(record.facets),
|
||||
facets: record.facets,
|
||||
}),
|
||||
[record],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user