f8cdd6b9ae
* Split out NotificationsTab * Remove unused route parameter * Refine the split between components * Hoist some logic out of NotificationFeed * Remove unused option * Add all|conversations to query, hardcode "all" * Add a Conversations tab * Rename to Mentions * Bump packages * Rename fields * Fix oopsie * Simplify header * Track active tab * Fix types * Separate logic for tabs * Better border for first unread * Highlight unread for all only * Fix spinner races * Fix fetchPage races * Fix bottom bar border being obscured by glimmer * Remember last tab within the session * One tab at a time * Fix TS * Handle all RQKEY usages * Nit
82 lines
2.1 KiB
TypeScript
82 lines
2.1 KiB
TypeScript
import {
|
|
AppBskyActorDefs,
|
|
AppBskyEmbedRecord,
|
|
AppBskyEmbedRecordWithMedia,
|
|
AppBskyFeedDefs,
|
|
AppBskyFeedPost,
|
|
AtUri,
|
|
} from '@atproto/api'
|
|
import {InfiniteData, QueryClient, QueryKey} from '@tanstack/react-query'
|
|
|
|
export async function truncateAndInvalidate<T = any>(
|
|
queryClient: QueryClient,
|
|
queryKey: QueryKey,
|
|
) {
|
|
queryClient.setQueriesData<InfiniteData<T>>({queryKey}, data => {
|
|
if (data) {
|
|
return {
|
|
pageParams: data.pageParams.slice(0, 1),
|
|
pages: data.pages.slice(0, 1),
|
|
}
|
|
}
|
|
return data
|
|
})
|
|
return queryClient.invalidateQueries({queryKey})
|
|
}
|
|
|
|
// Given an AtUri, this function will check if the AtUri matches a
|
|
// hit regardless of whether the AtUri uses a DID or handle as a host.
|
|
//
|
|
// AtUri should be the URI that is being searched for, while currentUri
|
|
// is the URI that is being checked. currentAuthor is the author
|
|
// of the currentUri that is being checked.
|
|
export function didOrHandleUriMatches(
|
|
atUri: AtUri,
|
|
record: {uri: string; author: AppBskyActorDefs.ProfileViewBasic},
|
|
) {
|
|
if (atUri.host.startsWith('did:')) {
|
|
return atUri.href === record.uri
|
|
}
|
|
|
|
return atUri.host === record.author.handle && record.uri.endsWith(atUri.rkey)
|
|
}
|
|
|
|
export function getEmbeddedPost(
|
|
v: unknown,
|
|
): AppBskyEmbedRecord.ViewRecord | undefined {
|
|
if (AppBskyEmbedRecord.isView(v)) {
|
|
if (
|
|
AppBskyEmbedRecord.isViewRecord(v.record) &&
|
|
AppBskyFeedPost.isRecord(v.record.value)
|
|
) {
|
|
return v.record
|
|
}
|
|
}
|
|
if (AppBskyEmbedRecordWithMedia.isView(v)) {
|
|
if (
|
|
AppBskyEmbedRecord.isViewRecord(v.record.record) &&
|
|
AppBskyFeedPost.isRecord(v.record.record.value)
|
|
) {
|
|
return v.record.record
|
|
}
|
|
}
|
|
}
|
|
|
|
export function embedViewRecordToPostView(
|
|
v: AppBskyEmbedRecord.ViewRecord,
|
|
): AppBskyFeedDefs.PostView {
|
|
return {
|
|
uri: v.uri,
|
|
cid: v.cid,
|
|
author: v.author,
|
|
record: v.value,
|
|
indexedAt: v.indexedAt,
|
|
labels: v.labels,
|
|
embed: v.embeds?.[0],
|
|
likeCount: v.likeCount,
|
|
quoteCount: v.quoteCount,
|
|
replyCount: v.replyCount,
|
|
repostCount: v.repostCount,
|
|
}
|
|
}
|