This commit is contained in:
Eric Bailey
2024-08-05 10:22:02 -05:00
parent a5676e5cb4
commit 9be0d49e78
3 changed files with 99 additions and 75 deletions
+71
View File
@@ -0,0 +1,71 @@
import {AppBskyFeedThreadgate, AtUri, BskyAgent} from '@atproto/api'
import {useQuery} from '@tanstack/react-query'
import {useAgent} from '#/state/session'
export * from '#/state/queries/threadgate/types'
export * from '#/state/queries/threadgate/util'
export const threadgateRecordQueryKeyRoot = 'threadgate-record'
export const createThreadgateRecordQueryKey = (uri: string) => [
threadgateRecordQueryKeyRoot,
uri,
]
export function useThreadgateRecordQuery({
postUri,
initialData,
}: {
postUri?: string
initialData?: AppBskyFeedThreadgate.Record
} = {}) {
const agent = useAgent()
return useQuery({
enabled: !!postUri,
queryKey: createThreadgateRecordQueryKey(postUri || ''),
placeholderData: initialData,
async queryFn() {
const urip = new AtUri(postUri!)
if (!urip.host.startsWith('did:')) {
const res = await agent.resolveHandle({
handle: urip.host,
})
urip.host = res.data.did
}
const {value} = await agent.api.app.bsky.feed.threadgate.get({
repo: urip.host,
rkey: urip.rkey,
})
return value
},
})
}
export function createThreadgate({
agent,
postUri,
threadgate,
}: {
agent: BskyAgent
postUri: string
threadgate: Partial<AppBskyFeedThreadgate.Record>
}) {
const urip = new AtUri(postUri)
const record = {
...threadgate,
post: postUri,
createdAt: new Date().toISOString(),
}
return agent.api.app.bsky.feed.threadgate.create(
{
repo: urip.host,
rkey: urip.rkey,
},
record,
)
}
+5
View File
@@ -0,0 +1,5 @@
export type ThreadgateAllowUISetting =
| {type: 'nobody'}
| {type: 'mention'}
| {type: 'following'}
| {type: 'list'; list: unknown}
+93
View File
@@ -0,0 +1,93 @@
import {AppBskyFeedDefs, AppBskyFeedThreadgate} from '@atproto/api'
import {ThreadgateAllowUISetting} from '#/state/queries/threadgate/types'
/**
* Converts a full {@link AppBskyFeedThreadgate.Record} to a list of
* {@link ThreadgateAllowUISetting}, for use by app UI.
*/
export function threadgateViewToAllowUISetting(
threadgate: AppBskyFeedDefs.ThreadgateView | undefined,
): ThreadgateAllowUISetting[] {
const record =
threadgate &&
AppBskyFeedThreadgate.isRecord(threadgate.record) &&
AppBskyFeedThreadgate.validateRecord(threadgate.record).success
? threadgate.record
: null
if (!record) {
return []
}
if (!record.allow?.length) {
return [{type: 'nobody'}]
}
const settings: ThreadgateAllowUISetting[] = record.allow
.map(allow => {
let setting: ThreadgateAllowUISetting | undefined
if (allow.$type === 'app.bsky.feed.threadgate#mentionRule') {
setting = {type: 'mention'}
} else if (allow.$type === 'app.bsky.feed.threadgate#followingRule') {
setting = {type: 'following'}
} else if (allow.$type === 'app.bsky.feed.threadgate#listRule') {
setting = {type: 'list', list: allow.list}
}
return setting
})
.filter(n => !!n)
return settings
}
/**
* Converts a list of {@link ThreadgateAllowUISetting} to the `allow` prop on
* {@link AppBskyFeedThreadgate.Record},
*/
export function threadgateAllowUISettingToAllowType(
threadgate: ThreadgateAllowUISetting[],
) {
let allow: (
| AppBskyFeedThreadgate.MentionRule
| AppBskyFeedThreadgate.FollowingRule
| AppBskyFeedThreadgate.ListRule
)[] = []
if (!threadgate.find(v => v.type === 'nobody')) {
for (const rule of threadgate) {
if (rule.type === 'mention') {
allow.push({$type: 'app.bsky.feed.threadgate#mentionRule'})
} else if (rule.type === 'following') {
allow.push({$type: 'app.bsky.feed.threadgate#followingRule'})
} else if (rule.type === 'list') {
allow.push({
$type: 'app.bsky.feed.threadgate#listRule',
list: rule.list,
})
}
}
}
return allow
}
/**
* Merges two {@link AppBskyFeedThreadgate.Record} objects, combining their
* `allow` and `hiddenReplies` arrays and de-deduplicating them.
*/
export function mergeThreadgateRecords(
prev: AppBskyFeedThreadgate.Record,
next: Partial<AppBskyFeedThreadgate.Record>,
): AppBskyFeedThreadgate.Record {
const allow = [...(prev.allow || []), ...(next.allow || [])].filter(
(v, i, a) => a.findIndex(t => t.$type === v.$type) === i,
)
const hiddenReplies = Array.from(
new Set([...(prev.hiddenReplies || []), ...(next.hiddenReplies || [])]),
)
return {
$type: 'app.bsky.feed.threadgate',
post: prev.post,
allow,
createdAt: new Date().toISOString(),
hiddenReplies,
}
}