Move remaining composer state into reducer (#5623)
Co-authored-by: Mary <git@mary.my.id> Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> Co-authored-by: Hailey <me@haileyok.com>
This commit is contained in:
+17
-28
@@ -4,7 +4,6 @@ import {
|
||||
AppBskyEmbedRecord,
|
||||
AppBskyEmbedRecordWithMedia,
|
||||
AppBskyEmbedVideo,
|
||||
AppBskyFeedPostgate,
|
||||
AtUri,
|
||||
BlobRef,
|
||||
BskyAgent,
|
||||
@@ -17,7 +16,7 @@ import {QueryClient} from '@tanstack/react-query'
|
||||
import {isNetworkError} from '#/lib/strings/errors'
|
||||
import {shortenLinks, stripInvalidMentions} from '#/lib/strings/rich-text-manip'
|
||||
import {logger} from '#/logger'
|
||||
import {ComposerImage, compressImage} from '#/state/gallery'
|
||||
import {compressImage} from '#/state/gallery'
|
||||
import {writePostgateRecord} from '#/state/queries/postgate'
|
||||
import {
|
||||
fetchResolveGifQuery,
|
||||
@@ -25,32 +24,18 @@ import {
|
||||
} from '#/state/queries/resolve-link'
|
||||
import {
|
||||
createThreadgateRecord,
|
||||
ThreadgateAllowUISetting,
|
||||
threadgateAllowUISettingToAllowRecordValue,
|
||||
writeThreadgateRecord,
|
||||
} from '#/state/queries/threadgate'
|
||||
import {ComposerState, EmbedDraft} from '#/view/com/composer/state/composer'
|
||||
import {ComposerDraft, EmbedDraft} from '#/view/com/composer/state/composer'
|
||||
import {createGIFDescription} from '../gif-alt-text'
|
||||
import {LinkMeta} from '../link-meta/link-meta'
|
||||
import {uploadBlob} from './upload-blob'
|
||||
|
||||
export {uploadBlob}
|
||||
|
||||
export interface ExternalEmbedDraft {
|
||||
uri: string
|
||||
isLoading: boolean
|
||||
meta?: LinkMeta
|
||||
embed?: AppBskyEmbedRecord.Main
|
||||
localThumb?: ComposerImage
|
||||
}
|
||||
|
||||
interface PostOpts {
|
||||
composerState: ComposerState // TODO: Not used yet.
|
||||
rawText: string
|
||||
draft: ComposerDraft
|
||||
replyTo?: string
|
||||
labels?: string[]
|
||||
threadgate: ThreadgateAllowUISetting[]
|
||||
postgate: AppBskyFeedPostgate.Record
|
||||
onStateChange?: (state: string) => void
|
||||
langs?: string[]
|
||||
}
|
||||
@@ -60,8 +45,12 @@ export async function post(
|
||||
queryClient: QueryClient,
|
||||
opts: PostOpts,
|
||||
) {
|
||||
const draft = opts.draft
|
||||
let reply
|
||||
let rt = new RichText({text: opts.rawText.trimEnd()}, {cleanNewlines: true})
|
||||
let rt = new RichText(
|
||||
{text: draft.richtext.text.trimEnd()},
|
||||
{cleanNewlines: true},
|
||||
)
|
||||
|
||||
opts.onStateChange?.('Processing...')
|
||||
|
||||
@@ -73,7 +62,7 @@ export async function post(
|
||||
const embed = await resolveEmbed(
|
||||
agent,
|
||||
queryClient,
|
||||
opts.composerState,
|
||||
draft,
|
||||
opts.onStateChange,
|
||||
)
|
||||
|
||||
@@ -98,10 +87,10 @@ export async function post(
|
||||
|
||||
// set labels
|
||||
let labels: ComAtprotoLabelDefs.SelfLabels | undefined
|
||||
if (opts.labels?.length) {
|
||||
if (draft.labels.length) {
|
||||
labels = {
|
||||
$type: 'com.atproto.label.defs#selfLabels',
|
||||
values: opts.labels.map(val => ({val})),
|
||||
values: draft.labels.map(val => ({val})),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +124,7 @@ export async function post(
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.threadgate.some(tg => tg.type !== 'everybody')) {
|
||||
if (draft.threadgate.some(tg => tg.type !== 'everybody')) {
|
||||
try {
|
||||
// TODO: this needs to be batch-created with the post!
|
||||
await writeThreadgateRecord({
|
||||
@@ -143,7 +132,7 @@ export async function post(
|
||||
postUri: res.uri,
|
||||
threadgate: createThreadgateRecord({
|
||||
post: res.uri,
|
||||
allow: threadgateAllowUISettingToAllowRecordValue(opts.threadgate),
|
||||
allow: threadgateAllowUISettingToAllowRecordValue(draft.threadgate),
|
||||
}),
|
||||
})
|
||||
} catch (e: any) {
|
||||
@@ -158,8 +147,8 @@ export async function post(
|
||||
}
|
||||
|
||||
if (
|
||||
opts.postgate.embeddingRules?.length ||
|
||||
opts.postgate.detachedEmbeddingUris?.length
|
||||
draft.postgate.embeddingRules?.length ||
|
||||
draft.postgate.detachedEmbeddingUris?.length
|
||||
) {
|
||||
try {
|
||||
// TODO: this needs to be batch-created with the post!
|
||||
@@ -167,7 +156,7 @@ export async function post(
|
||||
agent,
|
||||
postUri: res.uri,
|
||||
postgate: {
|
||||
...opts.postgate,
|
||||
...draft.postgate,
|
||||
post: res.uri,
|
||||
},
|
||||
})
|
||||
@@ -188,7 +177,7 @@ export async function post(
|
||||
async function resolveEmbed(
|
||||
agent: BskyAgent,
|
||||
queryClient: QueryClient,
|
||||
draft: ComposerState,
|
||||
draft: ComposerDraft,
|
||||
onStateChange: ((state: string) => void) | undefined,
|
||||
): Promise<
|
||||
| AppBskyEmbedImages.Main
|
||||
|
||||
+68
-25
@@ -1,17 +1,20 @@
|
||||
import {AppBskyActorDefs, ComAtprotoRepoStrongRef} from '@atproto/api'
|
||||
import {
|
||||
AppBskyActorDefs,
|
||||
AppBskyFeedPost,
|
||||
AppBskyGraphStarterpack,
|
||||
ComAtprotoRepoStrongRef,
|
||||
} from '@atproto/api'
|
||||
import {AtUri} from '@atproto/api'
|
||||
import {BskyAgent} from '@atproto/api'
|
||||
|
||||
import {POST_IMG_MAX} from '#/lib/constants'
|
||||
import {
|
||||
getFeedAsEmbed,
|
||||
getListAsEmbed,
|
||||
getPostAsQuote,
|
||||
getStarterPackAsEmbed,
|
||||
} from '#/lib/link-meta/bsky'
|
||||
import {getLinkMeta} from '#/lib/link-meta/link-meta'
|
||||
import {resolveShortLink} from '#/lib/link-meta/resolve-short-link'
|
||||
import {downloadAndResize} from '#/lib/media/manip'
|
||||
import {
|
||||
createStarterPackUri,
|
||||
parseStarterPackUri,
|
||||
} from '#/lib/strings/starter-pack'
|
||||
import {
|
||||
isBskyCustomFeedUrl,
|
||||
isBskyListUrl,
|
||||
@@ -24,6 +27,7 @@ import {ComposerImage} from '#/state/gallery'
|
||||
import {createComposerImage} from '#/state/gallery'
|
||||
import {Gif} from '#/state/queries/tenor'
|
||||
import {createGIFDescription} from '../gif-alt-text'
|
||||
import {convertBskyAppUrlIfNeeded, makeRecordUri} from '../strings/url-helpers'
|
||||
|
||||
type ResolvedExternalLink = {
|
||||
type: 'external'
|
||||
@@ -60,6 +64,12 @@ export type ResolvedLink =
|
||||
| ResolvedPostRecord
|
||||
| ResolvedOtherRecord
|
||||
|
||||
class EmbeddingDisabledError extends Error {
|
||||
constructor() {
|
||||
super('Embedding is disabled for this record')
|
||||
}
|
||||
}
|
||||
|
||||
export async function resolveLink(
|
||||
agent: BskyAgent,
|
||||
uri: string,
|
||||
@@ -68,55 +78,88 @@ export async function resolveLink(
|
||||
uri = await resolveShortLink(uri)
|
||||
}
|
||||
if (isBskyPostUrl(uri)) {
|
||||
// TODO: Remove this abstraction.
|
||||
// TODO: Nice error messages (e.g. EmbeddingDisabledError).
|
||||
const result = await getPostAsQuote(getPost, uri)
|
||||
uri = convertBskyAppUrlIfNeeded(uri)
|
||||
const [_0, user, _1, rkey] = uri.split('/').filter(Boolean)
|
||||
const recordUri = makeRecordUri(user, 'app.bsky.feed.post', rkey)
|
||||
const post = await getPost({uri: recordUri})
|
||||
if (post.viewer?.embeddingDisabled) {
|
||||
throw new EmbeddingDisabledError()
|
||||
}
|
||||
return {
|
||||
type: 'record',
|
||||
record: {
|
||||
cid: result.cid,
|
||||
uri: result.uri,
|
||||
cid: post.cid,
|
||||
uri: post.uri,
|
||||
},
|
||||
kind: 'post',
|
||||
meta: result,
|
||||
meta: {
|
||||
text: AppBskyFeedPost.isRecord(post.record) ? post.record.text : '',
|
||||
indexedAt: post.indexedAt,
|
||||
author: post.author,
|
||||
},
|
||||
}
|
||||
}
|
||||
if (isBskyCustomFeedUrl(uri)) {
|
||||
// TODO: Remove this abstraction.
|
||||
const result = await getFeedAsEmbed(agent, fetchDid, uri)
|
||||
uri = convertBskyAppUrlIfNeeded(uri)
|
||||
const [_0, handleOrDid, _1, rkey] = uri.split('/').filter(Boolean)
|
||||
const did = await fetchDid(handleOrDid)
|
||||
const feed = makeRecordUri(did, 'app.bsky.feed.generator', rkey)
|
||||
const res = await agent.app.bsky.feed.getFeedGenerator({feed})
|
||||
return {
|
||||
type: 'record',
|
||||
record: result.embed!.record,
|
||||
record: {
|
||||
uri: res.data.view.uri,
|
||||
cid: res.data.view.cid,
|
||||
},
|
||||
kind: 'other',
|
||||
meta: {
|
||||
// TODO: Include hydrated content instead.
|
||||
title: result.meta!.title!,
|
||||
title: res.data.view.displayName,
|
||||
},
|
||||
}
|
||||
}
|
||||
if (isBskyListUrl(uri)) {
|
||||
// TODO: Remove this abstraction.
|
||||
const result = await getListAsEmbed(agent, fetchDid, uri)
|
||||
uri = convertBskyAppUrlIfNeeded(uri)
|
||||
const [_0, handleOrDid, _1, rkey] = uri.split('/').filter(Boolean)
|
||||
const did = await fetchDid(handleOrDid)
|
||||
const list = makeRecordUri(did, 'app.bsky.graph.list', rkey)
|
||||
const res = await agent.app.bsky.graph.getList({list})
|
||||
return {
|
||||
type: 'record',
|
||||
record: result.embed!.record,
|
||||
record: {
|
||||
uri: res.data.list.uri,
|
||||
cid: res.data.list.cid,
|
||||
},
|
||||
kind: 'other',
|
||||
meta: {
|
||||
// TODO: Include hydrated content instead.
|
||||
title: result.meta!.title!,
|
||||
title: res.data.list.name,
|
||||
},
|
||||
}
|
||||
}
|
||||
if (isBskyStartUrl(uri) || isBskyStarterPackUrl(uri)) {
|
||||
// TODO: Remove this abstraction.
|
||||
const result = await getStarterPackAsEmbed(agent, fetchDid, uri)
|
||||
const parsed = parseStarterPackUri(uri)
|
||||
if (!parsed) {
|
||||
throw new Error(
|
||||
'Unexpectedly called getStarterPackAsEmbed with a non-starterpack url',
|
||||
)
|
||||
}
|
||||
const did = await fetchDid(parsed.name)
|
||||
const starterPack = createStarterPackUri({did, rkey: parsed.rkey})
|
||||
const res = await agent.app.bsky.graph.getStarterPack({starterPack})
|
||||
const record = res.data.starterPack.record
|
||||
return {
|
||||
type: 'record',
|
||||
record: result.embed!.record,
|
||||
record: {
|
||||
uri: res.data.starterPack.uri,
|
||||
cid: res.data.starterPack.cid,
|
||||
},
|
||||
kind: 'other',
|
||||
meta: {
|
||||
// TODO: Include hydrated content instead.
|
||||
title: result.meta!.title!,
|
||||
title: AppBskyGraphStarterpack.isRecord(record)
|
||||
? record.name
|
||||
: 'Starter Pack',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user