BlueSky & more on desktop lazurite.stormlightlabs.org/
tauri rust typescript bluesky appview atproto solid
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 99 lines 2.9 kB view raw
1import type { NormalizedEmbed } from "../feeds"; 2import { asRecord } from "../type-guards"; 3import type { 4 BlockedPost, 5 EmbedView, 6 FeedReplyNode, 7 FeedViewPost, 8 Maybe, 9 NotFoundPost, 10 PostView, 11 ProfileViewBasic, 12 ThreadNode, 13 ThreadViewPost, 14} from "../types"; 15 16export function isPostView(value: unknown): value is PostView { 17 const record = asRecord(value); 18 const author = asRecord(record?.author); 19 const postRecord = asRecord(record?.record); 20 21 return !!record 22 && !!author 23 && !!postRecord 24 && typeof record.cid === "string" 25 && typeof record.indexedAt === "string" 26 && typeof record.uri === "string" 27 && isProfileViewBasic(author); 28} 29 30export function isFeedViewPost(value: unknown): value is FeedViewPost { 31 const record = asRecord(value); 32 return !!record && isPostView(record.post); 33} 34 35export function isThreadNode(value: unknown): value is ThreadNode { 36 const record = asRecord(value); 37 if (!record || typeof record.$type !== "string") { 38 return false; 39 } 40 41 if (record.$type === "app.bsky.feed.defs#threadViewPost") { 42 return isPostView(record.post); 43 } 44 45 return record.$type === "app.bsky.feed.defs#blockedPost" || record.$type === "app.bsky.feed.defs#notFoundPost"; 46} 47 48export function isRepostReason(item: FeedViewPost) { 49 return item.reason?.$type === "app.bsky.feed.defs#reasonRepost"; 50} 51 52export function isQuoteEmbed(embed: Maybe<EmbedView>) { 53 return embed?.$type === "app.bsky.embed.record#view" || embed?.$type === "app.bsky.embed.recordWithMedia#view"; 54} 55 56export function isReplyItem(item: FeedViewPost) { 57 if (item.reply) { 58 return true; 59 } 60 61 const record = asRecord(item.post.record); 62 return !!asRecord(record?.reply); 63} 64 65export function isReplyByUnfollowed(item: FeedViewPost) { 66 return isReplyItem(item) && !item.post.author.viewer?.following; 67} 68 69export function isThreadViewPost(node: Maybe<ThreadNode>): node is ThreadViewPost { 70 return !!node && node.$type === "app.bsky.feed.defs#threadViewPost"; 71} 72 73export function isBlockedNode(node: Maybe<ThreadNode | FeedReplyNode>): node is BlockedPost { 74 return !!node && node.$type === "app.bsky.feed.defs#blockedPost"; 75} 76 77export function isNotFoundNode(node: Maybe<ThreadNode | FeedReplyNode>): node is NotFoundPost { 78 return !!node && node.$type === "app.bsky.feed.defs#notFoundPost"; 79} 80 81export function isProfileViewBasic(value: unknown): value is ProfileViewBasic { 82 const record = asRecord(value); 83 return !!record && typeof record.did === "string" && typeof record.handle === "string"; 84} 85 86export function isNormalizedEmbed(value: unknown): value is NormalizedEmbed { 87 if (!value || typeof value !== "object") { 88 return false; 89 } 90 91 const kind = (value as { kind?: unknown }).kind; 92 return kind === "external" 93 || kind === "images" 94 || kind === "record" 95 || kind === "recordWithMedia" 96 || kind === "recognized-unrenderable" 97 || kind === "unknown" 98 || kind === "video"; 99}