[Notifications] Add a Mentions tab (#7044)
* 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
This commit is contained in:
+2
-2
@@ -54,7 +54,7 @@
|
|||||||
"icons:optimize": "svgo -f ./assets/icons"
|
"icons:optimize": "svgo -f ./assets/icons"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@atproto/api": "^0.13.18",
|
"@atproto/api": "^0.13.20",
|
||||||
"@bitdrift/react-native": "0.4.0",
|
"@bitdrift/react-native": "0.4.0",
|
||||||
"@braintree/sanitize-url": "^6.0.2",
|
"@braintree/sanitize-url": "^6.0.2",
|
||||||
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
|
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
|
||||||
@@ -206,7 +206,7 @@
|
|||||||
"zod": "^3.20.2"
|
"zod": "^3.20.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@atproto/dev-env": "^0.3.64",
|
"@atproto/dev-env": "^0.3.67",
|
||||||
"@babel/core": "^7.26.0",
|
"@babel/core": "^7.26.0",
|
||||||
"@babel/preset-env": "^7.26.0",
|
"@babel/preset-env": "^7.26.0",
|
||||||
"@babel/runtime": "^7.26.0",
|
"@babel/runtime": "^7.26.0",
|
||||||
|
|||||||
@@ -239,14 +239,21 @@ export function useNotificationsHandler() {
|
|||||||
)
|
)
|
||||||
logEvent('notifications:openApp', {})
|
logEvent('notifications:openApp', {})
|
||||||
invalidateCachedUnreadPage()
|
invalidateCachedUnreadPage()
|
||||||
truncateAndInvalidate(queryClient, RQKEY_NOTIFS())
|
const payload = e.notification.request.trigger
|
||||||
|
.payload as NotificationPayload
|
||||||
|
truncateAndInvalidate(queryClient, RQKEY_NOTIFS('all'))
|
||||||
|
if (
|
||||||
|
payload.reason === 'mention' ||
|
||||||
|
payload.reason === 'quote' ||
|
||||||
|
payload.reason === 'reply'
|
||||||
|
) {
|
||||||
|
truncateAndInvalidate(queryClient, RQKEY_NOTIFS('mentions'))
|
||||||
|
}
|
||||||
logger.debug('Notifications: handleNotification', {
|
logger.debug('Notifications: handleNotification', {
|
||||||
content: e.notification.request.content,
|
content: e.notification.request.content,
|
||||||
payload: e.notification.request.trigger.payload,
|
payload: e.notification.request.trigger.payload,
|
||||||
})
|
})
|
||||||
handleNotification(
|
handleNotification(payload)
|
||||||
e.notification.request.trigger.payload as NotificationPayload,
|
|
||||||
)
|
|
||||||
Notifications.dismissAllNotificationsAsync()
|
Notifications.dismissAllNotificationsAsync()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ export type SearchTabNavigatorParams = CommonNavigatorParams & {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type NotificationsTabNavigatorParams = CommonNavigatorParams & {
|
export type NotificationsTabNavigatorParams = CommonNavigatorParams & {
|
||||||
Notifications: {show?: 'all'}
|
Notifications: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MyProfileTabNavigatorParams = CommonNavigatorParams & {
|
export type MyProfileTabNavigatorParams = CommonNavigatorParams & {
|
||||||
@@ -90,7 +90,7 @@ export type FlatNavigatorParams = CommonNavigatorParams & {
|
|||||||
Home: undefined
|
Home: undefined
|
||||||
Search: {q?: string}
|
Search: {q?: string}
|
||||||
Feeds: undefined
|
Feeds: undefined
|
||||||
Notifications: {show?: 'all'}
|
Notifications: undefined
|
||||||
Hashtag: {tag: string; author?: string}
|
Hashtag: {tag: string; author?: string}
|
||||||
Messages: {pushToConversation?: string; animation?: 'push' | 'pop'}
|
Messages: {pushToConversation?: string; animation?: 'push' | 'pop'}
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ export type AllNavigatorParams = CommonNavigatorParams & {
|
|||||||
Search: {q?: string}
|
Search: {q?: string}
|
||||||
Feeds: undefined
|
Feeds: undefined
|
||||||
NotificationsTab: undefined
|
NotificationsTab: undefined
|
||||||
Notifications: {show?: 'all'}
|
Notifications: undefined
|
||||||
MyProfileTab: undefined
|
MyProfileTab: undefined
|
||||||
Hashtag: {tag: string; author?: string}
|
Hashtag: {tag: string; author?: string}
|
||||||
MessagesTab: undefined
|
MessagesTab: undefined
|
||||||
|
|||||||
@@ -18,7 +18,13 @@ type Props = NativeStackScreenProps<AllNavigatorParams, 'NotificationSettings'>
|
|||||||
export function NotificationSettingsScreen({}: Props) {
|
export function NotificationSettingsScreen({}: Props) {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
|
||||||
const {data, isError: isQueryError, refetch} = useNotificationFeedQuery()
|
const {
|
||||||
|
data,
|
||||||
|
isError: isQueryError,
|
||||||
|
refetch,
|
||||||
|
} = useNotificationFeedQuery({
|
||||||
|
filter: 'all',
|
||||||
|
})
|
||||||
const serverPriority = data?.pages.at(0)?.priority
|
const serverPriority = data?.pages.at(0)?.priority
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -52,25 +52,22 @@ const PAGE_SIZE = 30
|
|||||||
type RQPageParam = string | undefined
|
type RQPageParam = string | undefined
|
||||||
|
|
||||||
const RQKEY_ROOT = 'notification-feed'
|
const RQKEY_ROOT = 'notification-feed'
|
||||||
export function RQKEY(priority?: false) {
|
export function RQKEY(filter: 'all' | 'mentions') {
|
||||||
return [RQKEY_ROOT, priority]
|
return [RQKEY_ROOT, filter]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useNotificationFeedQuery(opts?: {
|
export function useNotificationFeedQuery(opts: {
|
||||||
enabled?: boolean
|
enabled?: boolean
|
||||||
overridePriorityNotifications?: boolean
|
filter: 'all' | 'mentions'
|
||||||
}) {
|
}) {
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
const unreads = useUnreadNotificationsApi()
|
const unreads = useUnreadNotificationsApi()
|
||||||
const enabled = opts?.enabled !== false
|
const enabled = opts.enabled !== false
|
||||||
|
const filter = opts.filter
|
||||||
const {uris: hiddenReplyUris} = useThreadgateHiddenReplyUris()
|
const {uris: hiddenReplyUris} = useThreadgateHiddenReplyUris()
|
||||||
|
|
||||||
// false: force showing all notifications
|
|
||||||
// undefined: let the server decide
|
|
||||||
const priority = opts?.overridePriorityNotifications ? false : undefined
|
|
||||||
|
|
||||||
const selectArgs = useMemo(() => {
|
const selectArgs = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
@@ -91,14 +88,23 @@ export function useNotificationFeedQuery(opts?: {
|
|||||||
RQPageParam
|
RQPageParam
|
||||||
>({
|
>({
|
||||||
staleTime: STALE.INFINITY,
|
staleTime: STALE.INFINITY,
|
||||||
queryKey: RQKEY(priority),
|
queryKey: RQKEY(filter),
|
||||||
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
||||||
let page
|
let page
|
||||||
if (!pageParam) {
|
if (filter === 'all' && !pageParam) {
|
||||||
// for the first page, we check the cached page held by the unread-checker first
|
// for the first page, we check the cached page held by the unread-checker first
|
||||||
page = unreads.getCachedUnreadPage()
|
page = unreads.getCachedUnreadPage()
|
||||||
}
|
}
|
||||||
if (!page) {
|
if (!page) {
|
||||||
|
let reasons: string[] = []
|
||||||
|
if (filter === 'mentions') {
|
||||||
|
reasons = [
|
||||||
|
// Anything that's a post
|
||||||
|
'mention',
|
||||||
|
'reply',
|
||||||
|
'quote',
|
||||||
|
]
|
||||||
|
}
|
||||||
const {page: fetchedPage} = await fetchPage({
|
const {page: fetchedPage} = await fetchPage({
|
||||||
agent,
|
agent,
|
||||||
limit: PAGE_SIZE,
|
limit: PAGE_SIZE,
|
||||||
@@ -106,13 +112,13 @@ export function useNotificationFeedQuery(opts?: {
|
|||||||
queryClient,
|
queryClient,
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
fetchAdditionalData: true,
|
fetchAdditionalData: true,
|
||||||
priority,
|
reasons,
|
||||||
})
|
})
|
||||||
page = fetchedPage
|
page = fetchedPage
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the first page has an unread, mark all read
|
if (filter === 'all' && !pageParam) {
|
||||||
if (!pageParam) {
|
// if the first page has an unread, mark all read
|
||||||
unreads.markAllRead()
|
unreads.markAllRead()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ export function useNotificationSettingsMutation() {
|
|||||||
},
|
},
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
invalidateCachedUnreadPage()
|
invalidateCachedUnreadPage()
|
||||||
queryClient.invalidateQueries({queryKey: RQKEY_NOTIFS()})
|
queryClient.invalidateQueries({queryKey: RQKEY_NOTIFS('all')})
|
||||||
|
queryClient.invalidateQueries({queryKey: RQKEY_NOTIFS('mentions')})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -54,7 +55,7 @@ function eagerlySetCachedPriority(
|
|||||||
queryClient: ReturnType<typeof useQueryClient>,
|
queryClient: ReturnType<typeof useQueryClient>,
|
||||||
enabled: boolean,
|
enabled: boolean,
|
||||||
) {
|
) {
|
||||||
queryClient.setQueryData(RQKEY_NOTIFS(), (old: any) => {
|
function updateData(old: any) {
|
||||||
if (!old) return old
|
if (!old) return old
|
||||||
return {
|
return {
|
||||||
...old,
|
...old,
|
||||||
@@ -65,5 +66,7 @@ function eagerlySetCachedPriority(
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
queryClient.setQueryData(RQKEY_NOTIFS('all'), updateData)
|
||||||
|
queryClient.setQueryData(RQKEY_NOTIFS('mentions'), updateData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* A kind of companion API to ./feed.ts. See that file for more info.
|
* A kind of companion API to ./feed.ts. See that file for more info.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react'
|
import React, {useRef} from 'react'
|
||||||
import {AppState} from 'react-native'
|
import {AppState} from 'react-native'
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
import EventEmitter from 'eventemitter3'
|
import EventEmitter from 'eventemitter3'
|
||||||
@@ -105,6 +105,8 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
}
|
}
|
||||||
}, [setNumUnread])
|
}, [setNumUnread])
|
||||||
|
|
||||||
|
const isFetchingRef = useRef(false)
|
||||||
|
|
||||||
// create API
|
// create API
|
||||||
const api = React.useMemo<ApiContext>(() => {
|
const api = React.useMemo<ApiContext>(() => {
|
||||||
return {
|
return {
|
||||||
@@ -138,6 +140,12 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isFetchingRef.current) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Do not move this without ensuring it gets a symmetrical reset in the finally block.
|
||||||
|
isFetchingRef.current = true
|
||||||
|
|
||||||
// count
|
// count
|
||||||
const {page, indexedAt: lastIndexed} = await fetchPage({
|
const {page, indexedAt: lastIndexed} = await fetchPage({
|
||||||
agent,
|
agent,
|
||||||
@@ -145,6 +153,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
limit: 40,
|
limit: 40,
|
||||||
queryClient,
|
queryClient,
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
|
reasons: [],
|
||||||
|
|
||||||
// only fetch subjects when the page is going to be used
|
// only fetch subjects when the page is going to be used
|
||||||
// in the notifications query, otherwise skip it
|
// in the notifications query, otherwise skip it
|
||||||
@@ -174,11 +183,14 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
// update & broadcast
|
// update & broadcast
|
||||||
setNumUnread(unreadCountStr)
|
setNumUnread(unreadCountStr)
|
||||||
if (invalidate) {
|
if (invalidate) {
|
||||||
truncateAndInvalidate(queryClient, RQKEY_NOTIFS())
|
truncateAndInvalidate(queryClient, RQKEY_NOTIFS('all'))
|
||||||
|
truncateAndInvalidate(queryClient, RQKEY_NOTIFS('mentions'))
|
||||||
}
|
}
|
||||||
broadcast.postMessage({event: unreadCountStr})
|
broadcast.postMessage({event: unreadCountStr})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.warn('Failed to check unread notifications', {error: e})
|
logger.warn('Failed to check unread notifications', {error: e})
|
||||||
|
} finally {
|
||||||
|
isFetchingRef.current = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export async function fetchPage({
|
|||||||
queryClient,
|
queryClient,
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
fetchAdditionalData,
|
fetchAdditionalData,
|
||||||
|
reasons,
|
||||||
}: {
|
}: {
|
||||||
agent: BskyAgent
|
agent: BskyAgent
|
||||||
cursor: string | undefined
|
cursor: string | undefined
|
||||||
@@ -38,7 +39,7 @@ export async function fetchPage({
|
|||||||
queryClient: QueryClient
|
queryClient: QueryClient
|
||||||
moderationOpts: ModerationOpts | undefined
|
moderationOpts: ModerationOpts | undefined
|
||||||
fetchAdditionalData: boolean
|
fetchAdditionalData: boolean
|
||||||
priority?: boolean
|
reasons: string[]
|
||||||
}): Promise<{
|
}): Promise<{
|
||||||
page: FeedPage
|
page: FeedPage
|
||||||
indexedAt: string | undefined
|
indexedAt: string | undefined
|
||||||
@@ -46,7 +47,7 @@ export async function fetchPage({
|
|||||||
const res = await agent.listNotifications({
|
const res = await agent.listNotifications({
|
||||||
limit,
|
limit,
|
||||||
cursor,
|
cursor,
|
||||||
// priority,
|
reasons,
|
||||||
})
|
})
|
||||||
|
|
||||||
const indexedAt = res.data.notifications[0]?.indexedAt
|
const indexedAt = res.data.notifications[0]?.indexedAt
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {InfiniteData, QueryClient, QueryKey} from '@tanstack/react-query'
|
import {InfiniteData, QueryClient, QueryKey} from '@tanstack/react-query'
|
||||||
|
|
||||||
export function truncateAndInvalidate<T = any>(
|
export async function truncateAndInvalidate<T = any>(
|
||||||
queryClient: QueryClient,
|
queryClient: QueryClient,
|
||||||
queryKey: QueryKey,
|
queryKey: QueryKey,
|
||||||
) {
|
) {
|
||||||
@@ -21,7 +21,7 @@ export function truncateAndInvalidate<T = any>(
|
|||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
})
|
})
|
||||||
queryClient.invalidateQueries({queryKey})
|
return queryClient.invalidateQueries({queryKey})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given an AtUri, this function will check if the AtUri matches a
|
// Given an AtUri, this function will check if the AtUri matches a
|
||||||
|
|||||||
@@ -9,13 +9,11 @@ import {msg} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
||||||
import {usePalette} from '#/lib/hooks/usePalette'
|
|
||||||
import {cleanError} from '#/lib/strings/errors'
|
import {cleanError} from '#/lib/strings/errors'
|
||||||
import {s} from '#/lib/styles'
|
import {s} from '#/lib/styles'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||||
import {useNotificationFeedQuery} from '#/state/queries/notifications/feed'
|
import {useNotificationFeedQuery} from '#/state/queries/notifications/feed'
|
||||||
import {useUnreadNotificationsApi} from '#/state/queries/notifications/unread'
|
|
||||||
import {EmptyState} from '#/view/com/util/EmptyState'
|
import {EmptyState} from '#/view/com/util/EmptyState'
|
||||||
import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
|
import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
|
||||||
import {List, ListRef} from '#/view/com/util/List'
|
import {List, ListRef} from '#/view/com/util/List'
|
||||||
@@ -28,26 +26,26 @@ const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'}
|
|||||||
const LOADING_ITEM = {_reactKey: '__loading__'}
|
const LOADING_ITEM = {_reactKey: '__loading__'}
|
||||||
|
|
||||||
export function NotificationFeed({
|
export function NotificationFeed({
|
||||||
|
filter,
|
||||||
|
enabled,
|
||||||
scrollElRef,
|
scrollElRef,
|
||||||
onPressTryAgain,
|
onPressTryAgain,
|
||||||
onScrolledDownChange,
|
onScrolledDownChange,
|
||||||
ListHeaderComponent,
|
ListHeaderComponent,
|
||||||
overridePriorityNotifications,
|
refreshNotifications,
|
||||||
}: {
|
}: {
|
||||||
|
filter: 'all' | 'mentions'
|
||||||
|
enabled: boolean
|
||||||
scrollElRef?: ListRef
|
scrollElRef?: ListRef
|
||||||
onPressTryAgain?: () => void
|
onPressTryAgain?: () => void
|
||||||
onScrolledDownChange: (isScrolledDown: boolean) => void
|
onScrolledDownChange: (isScrolledDown: boolean) => void
|
||||||
ListHeaderComponent?: () => JSX.Element
|
ListHeaderComponent?: () => JSX.Element
|
||||||
overridePriorityNotifications?: boolean
|
refreshNotifications: () => Promise<void>
|
||||||
}) {
|
}) {
|
||||||
const initialNumToRender = useInitialNumToRender()
|
const initialNumToRender = useInitialNumToRender()
|
||||||
|
|
||||||
const [isPTRing, setIsPTRing] = React.useState(false)
|
const [isPTRing, setIsPTRing] = React.useState(false)
|
||||||
const pal = usePalette('default')
|
|
||||||
|
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
const {checkUnread} = useUnreadNotificationsApi()
|
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
isFetching,
|
isFetching,
|
||||||
@@ -58,8 +56,8 @@ export function NotificationFeed({
|
|||||||
isFetchingNextPage,
|
isFetchingNextPage,
|
||||||
fetchNextPage,
|
fetchNextPage,
|
||||||
} = useNotificationFeedQuery({
|
} = useNotificationFeedQuery({
|
||||||
enabled: !!moderationOpts,
|
enabled: enabled && !!moderationOpts,
|
||||||
overridePriorityNotifications,
|
filter,
|
||||||
})
|
})
|
||||||
const isEmpty = !isFetching && !data?.pages[0]?.items.length
|
const isEmpty = !isFetching && !data?.pages[0]?.items.length
|
||||||
|
|
||||||
@@ -85,7 +83,7 @@ export function NotificationFeed({
|
|||||||
const onRefresh = React.useCallback(async () => {
|
const onRefresh = React.useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setIsPTRing(true)
|
setIsPTRing(true)
|
||||||
await checkUnread({invalidate: true})
|
await refreshNotifications()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Failed to refresh notifications feed', {
|
logger.error('Failed to refresh notifications feed', {
|
||||||
message: err,
|
message: err,
|
||||||
@@ -93,7 +91,7 @@ export function NotificationFeed({
|
|||||||
} finally {
|
} finally {
|
||||||
setIsPTRing(false)
|
setIsPTRing(false)
|
||||||
}
|
}
|
||||||
}, [checkUnread, setIsPTRing])
|
}, [refreshNotifications, setIsPTRing])
|
||||||
|
|
||||||
const onEndReached = React.useCallback(async () => {
|
const onEndReached = React.useCallback(async () => {
|
||||||
if (isFetching || !hasNextPage || isError) return
|
if (isFetching || !hasNextPage || isError) return
|
||||||
@@ -129,21 +127,18 @@ export function NotificationFeed({
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
} else if (item === LOADING_ITEM) {
|
} else if (item === LOADING_ITEM) {
|
||||||
return (
|
return <NotificationFeedLoadingPlaceholder />
|
||||||
<View style={[pal.border]}>
|
|
||||||
<NotificationFeedLoadingPlaceholder />
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<NotificationFeedItem
|
<NotificationFeedItem
|
||||||
|
highlightUnread={filter === 'all'}
|
||||||
item={item}
|
item={item}
|
||||||
moderationOpts={moderationOpts!}
|
moderationOpts={moderationOpts!}
|
||||||
hideTopBorder={index === 0}
|
hideTopBorder={index === 0 && item.notification.isRead}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[moderationOpts, _, onPressRetryLoadMore, pal.border],
|
[moderationOpts, _, onPressRetryLoadMore, filter],
|
||||||
)
|
)
|
||||||
|
|
||||||
const FeedFooter = React.useCallback(
|
const FeedFooter = React.useCallback(
|
||||||
|
|||||||
@@ -79,10 +79,12 @@ interface Author {
|
|||||||
let NotificationFeedItem = ({
|
let NotificationFeedItem = ({
|
||||||
item,
|
item,
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
|
highlightUnread,
|
||||||
hideTopBorder,
|
hideTopBorder,
|
||||||
}: {
|
}: {
|
||||||
item: FeedNotification
|
item: FeedNotification
|
||||||
moderationOpts: ModerationOpts
|
moderationOpts: ModerationOpts
|
||||||
|
highlightUnread: boolean
|
||||||
hideTopBorder?: boolean
|
hideTopBorder?: boolean
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
@@ -151,6 +153,7 @@ let NotificationFeedItem = ({
|
|||||||
if (!item.subject) {
|
if (!item.subject) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
const isHighlighted = highlightUnread && !item.notification.isRead
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
testID={`feedItem-by-${item.notification.author.handle}`}
|
testID={`feedItem-by-${item.notification.author.handle}`}
|
||||||
@@ -160,12 +163,10 @@ let NotificationFeedItem = ({
|
|||||||
<Post
|
<Post
|
||||||
post={item.subject}
|
post={item.subject}
|
||||||
style={
|
style={
|
||||||
item.notification.isRead
|
isHighlighted && {
|
||||||
? undefined
|
backgroundColor: pal.colors.unreadNotifBg,
|
||||||
: {
|
borderColor: pal.colors.unreadNotifBorder,
|
||||||
backgroundColor: pal.colors.unreadNotifBg,
|
}
|
||||||
borderColor: pal.colors.unreadNotifBorder,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
hideTopBorder={hideTopBorder}
|
hideTopBorder={hideTopBorder}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -136,12 +136,14 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View testID={testID} style={[a.flex_1, native(a.overflow_hidden)]}>
|
<View testID={testID} style={[a.flex_1, native(a.overflow_hidden)]}>
|
||||||
{renderTabBar({
|
<View style={a.z_10 /* Let tabbar bottom border cover the glimmer */}>
|
||||||
selectedPage,
|
{renderTabBar({
|
||||||
onSelect: onTabBarSelect,
|
selectedPage,
|
||||||
dragProgress,
|
onSelect: onTabBarSelect,
|
||||||
dragState,
|
dragProgress,
|
||||||
})}
|
dragState,
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
<GestureDetector gesture={nativeGesture}>
|
<GestureDetector gesture={nativeGesture}>
|
||||||
<AnimatedPagerView
|
<AnimatedPagerView
|
||||||
ref={pagerView}
|
ref={pagerView}
|
||||||
|
|||||||
@@ -872,7 +872,13 @@ function MockNotifItem({
|
|||||||
</P>
|
</P>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return <NotificationFeedItem item={notif} moderationOpts={moderationOpts} />
|
return (
|
||||||
|
<NotificationFeedItem
|
||||||
|
item={notif}
|
||||||
|
moderationOpts={moderationOpts}
|
||||||
|
highlightUnread
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function MockAccountCard({
|
function MockAccountCard({
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
} from '#/lib/routes/types'
|
} from '#/lib/routes/types'
|
||||||
import {s} from '#/lib/styles'
|
import {s} from '#/lib/styles'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
import {isNative} from '#/platform/detection'
|
||||||
import {emitSoftReset, listenSoftReset} from '#/state/events'
|
import {emitSoftReset, listenSoftReset} from '#/state/events'
|
||||||
import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed'
|
import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed'
|
||||||
import {
|
import {
|
||||||
@@ -24,35 +24,173 @@ import {truncateAndInvalidate} from '#/state/queries/util'
|
|||||||
import {useSetMinimalShellMode} from '#/state/shell'
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
import {useComposerControls} from '#/state/shell/composer'
|
import {useComposerControls} from '#/state/shell/composer'
|
||||||
import {NotificationFeed} from '#/view/com/notifications/NotificationFeed'
|
import {NotificationFeed} from '#/view/com/notifications/NotificationFeed'
|
||||||
|
import {Pager} from '#/view/com/pager/Pager'
|
||||||
|
import {TabBar} from '#/view/com/pager/TabBar'
|
||||||
import {FAB} from '#/view/com/util/fab/FAB'
|
import {FAB} from '#/view/com/util/fab/FAB'
|
||||||
import {ListMethods} from '#/view/com/util/List'
|
import {ListMethods} from '#/view/com/util/List'
|
||||||
import {LoadLatestBtn} from '#/view/com/util/load-latest/LoadLatestBtn'
|
import {LoadLatestBtn} from '#/view/com/util/load-latest/LoadLatestBtn'
|
||||||
import {MainScrollProvider} from '#/view/com/util/MainScrollProvider'
|
import {MainScrollProvider} from '#/view/com/util/MainScrollProvider'
|
||||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
import {atoms as a} from '#/alf'
|
||||||
import {Button, ButtonIcon} from '#/components/Button'
|
import {web} from '#/alf'
|
||||||
|
import {ButtonIcon} from '#/components/Button'
|
||||||
import {SettingsGear2_Stroke2_Corner0_Rounded as SettingsIcon} from '#/components/icons/SettingsGear2'
|
import {SettingsGear2_Stroke2_Corner0_Rounded as SettingsIcon} from '#/components/icons/SettingsGear2'
|
||||||
import * as Layout from '#/components/Layout'
|
import * as Layout from '#/components/Layout'
|
||||||
import {Link} from '#/components/Link'
|
import {Link} from '#/components/Link'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
|
|
||||||
|
// We don't currently persist this across reloads since
|
||||||
|
// you gotta visit All to clear the badge anyway.
|
||||||
|
// But let's at least persist it during the sesssion.
|
||||||
|
let lastActiveTab = 0
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<
|
type Props = NativeStackScreenProps<
|
||||||
NotificationsTabNavigatorParams,
|
NotificationsTabNavigatorParams,
|
||||||
'Notifications'
|
'Notifications'
|
||||||
>
|
>
|
||||||
export function NotificationsScreen({route: {params}}: Props) {
|
export function NotificationsScreen({}: Props) {
|
||||||
const t = useTheme()
|
const {_} = useLingui()
|
||||||
const {gtTablet} = useBreakpoints()
|
const {openComposer} = useComposerControls()
|
||||||
|
const unreadNotifs = useUnreadNotifications()
|
||||||
|
const hasNew = !!unreadNotifs
|
||||||
|
const {checkUnread: checkUnreadAll} = useUnreadNotificationsApi()
|
||||||
|
const [isLoadingAll, setIsLoadingAll] = React.useState(false)
|
||||||
|
const [isLoadingMentions, setIsLoadingMentions] = React.useState(false)
|
||||||
|
const initialActiveTab = lastActiveTab
|
||||||
|
const [activeTab, setActiveTab] = React.useState(initialActiveTab)
|
||||||
|
const isLoading = activeTab === 0 ? isLoadingAll : isLoadingMentions
|
||||||
|
|
||||||
|
const onPageSelected = React.useCallback(
|
||||||
|
(index: number) => {
|
||||||
|
setActiveTab(index)
|
||||||
|
lastActiveTab = index
|
||||||
|
},
|
||||||
|
[setActiveTab],
|
||||||
|
)
|
||||||
|
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
const checkUnreadMentions = React.useCallback(
|
||||||
|
async ({invalidate}: {invalidate: boolean}) => {
|
||||||
|
if (invalidate) {
|
||||||
|
return truncateAndInvalidate(queryClient, NOTIFS_RQKEY('mentions'))
|
||||||
|
} else {
|
||||||
|
// Background polling is not implemented for the mentions tab.
|
||||||
|
// Just ignore it.
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[queryClient],
|
||||||
|
)
|
||||||
|
|
||||||
|
const sections = React.useMemo(() => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
title: _(msg`All`),
|
||||||
|
component: (
|
||||||
|
<NotificationsTab
|
||||||
|
filter="all"
|
||||||
|
isActive={activeTab === 0}
|
||||||
|
isLoading={isLoadingAll}
|
||||||
|
hasNew={hasNew}
|
||||||
|
setIsLoadingLatest={setIsLoadingAll}
|
||||||
|
checkUnread={checkUnreadAll}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: _(msg`Mentions`),
|
||||||
|
component: (
|
||||||
|
<NotificationsTab
|
||||||
|
filter="mentions"
|
||||||
|
isActive={activeTab === 1}
|
||||||
|
isLoading={isLoadingMentions}
|
||||||
|
hasNew={false /* We don't know for sure */}
|
||||||
|
setIsLoadingLatest={setIsLoadingMentions}
|
||||||
|
checkUnread={checkUnreadMentions}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}, [
|
||||||
|
_,
|
||||||
|
hasNew,
|
||||||
|
checkUnreadAll,
|
||||||
|
checkUnreadMentions,
|
||||||
|
activeTab,
|
||||||
|
isLoadingAll,
|
||||||
|
isLoadingMentions,
|
||||||
|
])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout.Screen testID="notificationsScreen">
|
||||||
|
<Layout.Header.Outer noBottomBorder>
|
||||||
|
<Layout.Header.MenuButton />
|
||||||
|
<Layout.Header.Content>
|
||||||
|
<Layout.Header.TitleText>
|
||||||
|
<Trans>Notifications</Trans>
|
||||||
|
</Layout.Header.TitleText>
|
||||||
|
</Layout.Header.Content>
|
||||||
|
<Layout.Header.Slot>
|
||||||
|
<Link
|
||||||
|
to="/notifications/settings"
|
||||||
|
label={_(msg`Notification settings`)}
|
||||||
|
size="small"
|
||||||
|
variant="ghost"
|
||||||
|
color="secondary"
|
||||||
|
shape="round"
|
||||||
|
style={[a.justify_center]}>
|
||||||
|
<ButtonIcon icon={isLoading ? Loader : SettingsIcon} size="lg" />
|
||||||
|
</Link>
|
||||||
|
</Layout.Header.Slot>
|
||||||
|
</Layout.Header.Outer>
|
||||||
|
<Pager
|
||||||
|
onPageSelected={onPageSelected}
|
||||||
|
renderTabBar={props => (
|
||||||
|
<Layout.Center style={web([a.sticky, a.z_10, {top: 0}])}>
|
||||||
|
<TabBar
|
||||||
|
{...props}
|
||||||
|
items={sections.map(section => section.title)}
|
||||||
|
onPressSelected={() => emitSoftReset()}
|
||||||
|
/>
|
||||||
|
</Layout.Center>
|
||||||
|
)}
|
||||||
|
initialPage={initialActiveTab}>
|
||||||
|
{sections.map((section, i) => (
|
||||||
|
<View key={i}>{section.component}</View>
|
||||||
|
))}
|
||||||
|
</Pager>
|
||||||
|
<FAB
|
||||||
|
testID="composeFAB"
|
||||||
|
onPress={() => openComposer({})}
|
||||||
|
icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
|
||||||
|
accessibilityRole="button"
|
||||||
|
accessibilityLabel={_(msg`New post`)}
|
||||||
|
accessibilityHint=""
|
||||||
|
/>
|
||||||
|
</Layout.Screen>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function NotificationsTab({
|
||||||
|
filter,
|
||||||
|
isActive,
|
||||||
|
isLoading,
|
||||||
|
hasNew,
|
||||||
|
checkUnread,
|
||||||
|
setIsLoadingLatest,
|
||||||
|
}: {
|
||||||
|
filter: 'all' | 'mentions'
|
||||||
|
isActive: boolean
|
||||||
|
isLoading: boolean
|
||||||
|
hasNew: boolean
|
||||||
|
checkUnread: ({invalidate}: {invalidate: boolean}) => Promise<void>
|
||||||
|
setIsLoadingLatest: (v: boolean) => void
|
||||||
|
}) {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const setMinimalShellMode = useSetMinimalShellMode()
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
const [isScrolledDown, setIsScrolledDown] = React.useState(false)
|
const [isScrolledDown, setIsScrolledDown] = React.useState(false)
|
||||||
const [isLoadingLatest, setIsLoadingLatest] = React.useState(false)
|
|
||||||
const scrollElRef = React.useRef<ListMethods>(null)
|
const scrollElRef = React.useRef<ListMethods>(null)
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const unreadNotifs = useUnreadNotifications()
|
|
||||||
const unreadApi = useUnreadNotificationsApi()
|
|
||||||
const hasNew = !!unreadNotifs
|
|
||||||
const isScreenFocused = useIsFocused()
|
const isScreenFocused = useIsFocused()
|
||||||
const {openComposer} = useComposerControls()
|
const isFocusedAndActive = isScreenFocused && isActive
|
||||||
|
|
||||||
// event handlers
|
// event handlers
|
||||||
// =
|
// =
|
||||||
@@ -65,16 +203,23 @@ export function NotificationsScreen({route: {params}}: Props) {
|
|||||||
scrollToTop()
|
scrollToTop()
|
||||||
if (hasNew) {
|
if (hasNew) {
|
||||||
// render what we have now
|
// render what we have now
|
||||||
truncateAndInvalidate(queryClient, NOTIFS_RQKEY())
|
truncateAndInvalidate(queryClient, NOTIFS_RQKEY(filter))
|
||||||
} else {
|
} else if (!isLoading) {
|
||||||
// check with the server
|
// check with the server
|
||||||
setIsLoadingLatest(true)
|
setIsLoadingLatest(true)
|
||||||
unreadApi
|
checkUnread({invalidate: true})
|
||||||
.checkUnread({invalidate: true})
|
|
||||||
.catch(() => undefined)
|
.catch(() => undefined)
|
||||||
.then(() => setIsLoadingLatest(false))
|
.then(() => setIsLoadingLatest(false))
|
||||||
}
|
}
|
||||||
}, [scrollToTop, queryClient, unreadApi, hasNew, setIsLoadingLatest])
|
}, [
|
||||||
|
scrollToTop,
|
||||||
|
queryClient,
|
||||||
|
checkUnread,
|
||||||
|
hasNew,
|
||||||
|
isLoading,
|
||||||
|
setIsLoadingLatest,
|
||||||
|
filter,
|
||||||
|
])
|
||||||
|
|
||||||
const onFocusCheckLatest = useNonReactiveCallback(() => {
|
const onFocusCheckLatest = useNonReactiveCallback(() => {
|
||||||
// on focus, check for latest, but only invalidate if the user
|
// on focus, check for latest, but only invalidate if the user
|
||||||
@@ -87,79 +232,36 @@ export function NotificationsScreen({route: {params}}: Props) {
|
|||||||
// we're just going to look it up synchronously.
|
// we're just going to look it up synchronously.
|
||||||
currentIsScrolledDown = window.scrollY > 200
|
currentIsScrolledDown = window.scrollY > 200
|
||||||
}
|
}
|
||||||
unreadApi.checkUnread({invalidate: !currentIsScrolledDown})
|
checkUnread({invalidate: !currentIsScrolledDown})
|
||||||
})
|
})
|
||||||
|
|
||||||
// on-visible setup
|
// on-visible setup
|
||||||
// =
|
// =
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
React.useCallback(() => {
|
React.useCallback(() => {
|
||||||
setMinimalShellMode(false)
|
if (isFocusedAndActive) {
|
||||||
logger.debug('NotificationsScreen: Focus')
|
setMinimalShellMode(false)
|
||||||
onFocusCheckLatest()
|
logger.debug('NotificationsScreen: Focus')
|
||||||
}, [setMinimalShellMode, onFocusCheckLatest]),
|
onFocusCheckLatest()
|
||||||
|
}
|
||||||
|
}, [setMinimalShellMode, onFocusCheckLatest, isFocusedAndActive]),
|
||||||
)
|
)
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!isScreenFocused) {
|
if (!isFocusedAndActive) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return listenSoftReset(onPressLoadLatest)
|
return listenSoftReset(onPressLoadLatest)
|
||||||
}, [onPressLoadLatest, isScreenFocused])
|
}, [onPressLoadLatest, isFocusedAndActive])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout.Screen testID="notificationsScreen">
|
<>
|
||||||
<Layout.Header.Outer>
|
|
||||||
<Layout.Header.MenuButton />
|
|
||||||
<Layout.Header.Content>
|
|
||||||
<Button
|
|
||||||
label={_(msg`Notifications`)}
|
|
||||||
accessibilityHint={_(msg`Refresh notifications`)}
|
|
||||||
onPress={emitSoftReset}
|
|
||||||
style={[a.justify_start]}>
|
|
||||||
{({hovered}) => (
|
|
||||||
<Layout.Header.TitleText
|
|
||||||
style={[a.w_full, hovered && a.underline]}>
|
|
||||||
<Trans>Notifications</Trans>
|
|
||||||
{isWeb && gtTablet && hasNew && (
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
a.rounded_full,
|
|
||||||
{
|
|
||||||
width: 8,
|
|
||||||
height: 8,
|
|
||||||
bottom: 3,
|
|
||||||
left: 6,
|
|
||||||
backgroundColor: t.palette.primary_500,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Layout.Header.TitleText>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</Layout.Header.Content>
|
|
||||||
<Layout.Header.Slot>
|
|
||||||
<Link
|
|
||||||
to="/notifications/settings"
|
|
||||||
label={_(msg`Notification settings`)}
|
|
||||||
size="small"
|
|
||||||
variant="ghost"
|
|
||||||
color="secondary"
|
|
||||||
shape="round"
|
|
||||||
style={[a.justify_center]}>
|
|
||||||
<ButtonIcon
|
|
||||||
icon={isLoadingLatest ? Loader : SettingsIcon}
|
|
||||||
size="lg"
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
</Layout.Header.Slot>
|
|
||||||
</Layout.Header.Outer>
|
|
||||||
|
|
||||||
<MainScrollProvider>
|
<MainScrollProvider>
|
||||||
<NotificationFeed
|
<NotificationFeed
|
||||||
|
enabled={isFocusedAndActive}
|
||||||
|
filter={filter}
|
||||||
|
refreshNotifications={() => checkUnread({invalidate: true})}
|
||||||
onScrolledDownChange={setIsScrolledDown}
|
onScrolledDownChange={setIsScrolledDown}
|
||||||
scrollElRef={scrollElRef}
|
scrollElRef={scrollElRef}
|
||||||
overridePriorityNotifications={params?.show === 'all'}
|
|
||||||
/>
|
/>
|
||||||
</MainScrollProvider>
|
</MainScrollProvider>
|
||||||
{(isScrolledDown || hasNew) && (
|
{(isScrolledDown || hasNew) && (
|
||||||
@@ -169,14 +271,6 @@ export function NotificationsScreen({route: {params}}: Props) {
|
|||||||
showIndicator={hasNew}
|
showIndicator={hasNew}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<FAB
|
</>
|
||||||
testID="composeFAB"
|
|
||||||
onPress={() => openComposer({})}
|
|
||||||
icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
|
|
||||||
accessibilityRole="button"
|
|
||||||
accessibilityLabel={_(msg`New post`)}
|
|
||||||
accessibilityHint=""
|
|
||||||
/>
|
|
||||||
</Layout.Screen>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,21 +20,21 @@
|
|||||||
"@jridgewell/gen-mapping" "^0.3.0"
|
"@jridgewell/gen-mapping" "^0.3.0"
|
||||||
"@jridgewell/trace-mapping" "^0.3.9"
|
"@jridgewell/trace-mapping" "^0.3.9"
|
||||||
|
|
||||||
"@atproto-labs/fetch-node@0.1.3":
|
"@atproto-labs/fetch-node@0.1.4":
|
||||||
version "0.1.3"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto-labs/fetch-node/-/fetch-node-0.1.3.tgz#2581bf4710a4f957c74c75d959961de3304b3595"
|
resolved "https://registry.yarnpkg.com/@atproto-labs/fetch-node/-/fetch-node-0.1.4.tgz#03859a39556eab936e2b3bec2d087585c6408cb3"
|
||||||
integrity sha512-KX3ogPJt6dXNppWImQ9omfhrc8t73WrJaxHMphRAqQL8jXxKW5NBCTjSuwroBkJ1pj1aValBrc5NpdYu+H/9Qg==
|
integrity sha512-hwYx0XpgIl2zydRy13DtWvywruuHk1EX+yCjqjgUIezUm8fi35ZN4QvR6INEm0MpN2MD/kQsImPbd8ZftzZ3zw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto-labs/fetch" "0.1.1"
|
"@atproto-labs/fetch" "0.1.2"
|
||||||
"@atproto-labs/pipe" "0.1.0"
|
"@atproto-labs/pipe" "0.1.0"
|
||||||
ipaddr.js "^2.1.0"
|
ipaddr.js "^2.1.0"
|
||||||
psl "^1.9.0"
|
psl "^1.9.0"
|
||||||
undici "^6.14.1"
|
undici "^6.14.1"
|
||||||
|
|
||||||
"@atproto-labs/fetch@0.1.1":
|
"@atproto-labs/fetch@0.1.2":
|
||||||
version "0.1.1"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto-labs/fetch/-/fetch-0.1.1.tgz#10e7f8c06cf01a63f58e130b95d9ee0d4171902c"
|
resolved "https://registry.yarnpkg.com/@atproto-labs/fetch/-/fetch-0.1.2.tgz#e1b9354205fb76f106ae3e1c6b56e7865a39600f"
|
||||||
integrity sha512-X1zO1MDoJzEurbWXMAe1H8EZ995Xam/aXdxhGVrXmOMyPDuvBa1oxwh/kQNZRCKcMQUbiwkk+Jfq6ZkTuvGbww==
|
integrity sha512-7mQQIRtVenqtdBQKCqoLjyAhPS2aA56EGEjyz5zB3sramM3qkrvzyusr55GAzGDS0tvB6cy9cDEtSLmfK7LUnA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto-labs/pipe" "0.1.0"
|
"@atproto-labs/pipe" "0.1.0"
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@@ -58,28 +58,28 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@atproto-labs/simple-store/-/simple-store-0.1.1.tgz#e743a2722b5d8732166f0a72aca8bd10e9bff106"
|
resolved "https://registry.yarnpkg.com/@atproto-labs/simple-store/-/simple-store-0.1.1.tgz#e743a2722b5d8732166f0a72aca8bd10e9bff106"
|
||||||
integrity sha512-WKILW2b3QbAYKh+w5U2x6p5FqqLl0nAeLwGeDY+KjX01K4Dq3vQTR9b/qNp0jZm48CabPQVrqCv0PPU9LgRRRg==
|
integrity sha512-WKILW2b3QbAYKh+w5U2x6p5FqqLl0nAeLwGeDY+KjX01K4Dq3vQTR9b/qNp0jZm48CabPQVrqCv0PPU9LgRRRg==
|
||||||
|
|
||||||
"@atproto/api@^0.13.18":
|
"@atproto/api@^0.13.20":
|
||||||
version "0.13.18"
|
version "0.13.20"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.18.tgz#cc537cc3b4c8d03f258a373f4d893fea11a77cdd"
|
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.20.tgz#5140db303c3b0981958dfe6a5fa6d7d1cd7bb3cc"
|
||||||
integrity sha512-rrl5HhzGYWZ7fiC965TPBUOVItq9M4dxMb6qz8IvAVQliSkrJrKc7UD0QWL89QiiXaOBuX8w+4i5r4wrfBGddg==
|
integrity sha512-z/+CvG6BEttRHf856tKSe1AeUQNfrobRJldaHAthGmFk7O3wLZQyfcI9DUmBJQ9+4wAt0dZwvKWVGLZOV9eLHA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/common-web" "^0.3.1"
|
"@atproto/common-web" "^0.3.1"
|
||||||
"@atproto/lexicon" "^0.4.3"
|
"@atproto/lexicon" "^0.4.4"
|
||||||
"@atproto/syntax" "^0.3.1"
|
"@atproto/syntax" "^0.3.1"
|
||||||
"@atproto/xrpc" "^0.6.4"
|
"@atproto/xrpc" "^0.6.5"
|
||||||
await-lock "^2.2.2"
|
await-lock "^2.2.2"
|
||||||
multiformats "^9.9.0"
|
multiformats "^9.9.0"
|
||||||
tlds "^1.234.0"
|
tlds "^1.234.0"
|
||||||
zod "^3.23.8"
|
zod "^3.23.8"
|
||||||
|
|
||||||
"@atproto/aws@^0.2.9":
|
"@atproto/aws@^0.2.10":
|
||||||
version "0.2.9"
|
version "0.2.10"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/aws/-/aws-0.2.9.tgz#3539b281b725914b769451ee4afc62315dff1afc"
|
resolved "https://registry.yarnpkg.com/@atproto/aws/-/aws-0.2.10.tgz#e0b888fd50308cc24b7086cf3ec209587c13bbe4"
|
||||||
integrity sha512-sc9aXUePcqItkJSOJJnGNVthVfAKjhn3zMDG+RRLzKUBye6Yutrlhpt1yxNZLHQiqIK5fy2Cuc4EX3p3jeWUYw==
|
integrity sha512-zQElKk6wGTQo5aKdXtmx/dINjkVgbJU9+C/xOVTs+M88I8IrrBxPvo1dASLJcMtRb9VjXh5snLJeAjgyx6qC6Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/common" "^0.4.4"
|
"@atproto/common" "^0.4.5"
|
||||||
"@atproto/crypto" "^0.4.2"
|
"@atproto/crypto" "^0.4.2"
|
||||||
"@atproto/repo" "^0.5.5"
|
"@atproto/repo" "^0.6.0"
|
||||||
"@aws-sdk/client-cloudfront" "^3.261.0"
|
"@aws-sdk/client-cloudfront" "^3.261.0"
|
||||||
"@aws-sdk/client-kms" "^3.196.0"
|
"@aws-sdk/client-kms" "^3.196.0"
|
||||||
"@aws-sdk/client-s3" "^3.224.0"
|
"@aws-sdk/client-s3" "^3.224.0"
|
||||||
@@ -89,20 +89,20 @@
|
|||||||
multiformats "^9.9.0"
|
multiformats "^9.9.0"
|
||||||
uint8arrays "3.0.0"
|
uint8arrays "3.0.0"
|
||||||
|
|
||||||
"@atproto/bsky@^0.0.96":
|
"@atproto/bsky@^0.0.98":
|
||||||
version "0.0.96"
|
version "0.0.98"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/bsky/-/bsky-0.0.96.tgz#b89abf2828f57738357beb4efd05539667dd14b3"
|
resolved "https://registry.yarnpkg.com/@atproto/bsky/-/bsky-0.0.98.tgz#4c4746e588568df1878647ae80cf4b963bc95924"
|
||||||
integrity sha512-Tk0ppiPMKdcnPU3x+uBAVRn92vroznhr2OlqinNSy/PZ39qWViRlKAhG3CLJsU2gjSHxsNfaIwulj7tPvKCmSw==
|
integrity sha512-Y+un2pD1W1H0s0IWdY6S4vLy8rgR8cpqThz9onn4wDppmGWvOBNXeD8AjNzIWC0iFlYcfR4rwCKSoccUXYzxNg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/api" "^0.13.18"
|
"@atproto/api" "^0.13.20"
|
||||||
"@atproto/common" "^0.4.4"
|
"@atproto/common" "^0.4.5"
|
||||||
"@atproto/crypto" "^0.4.2"
|
"@atproto/crypto" "^0.4.2"
|
||||||
"@atproto/identity" "^0.4.3"
|
"@atproto/identity" "^0.4.3"
|
||||||
"@atproto/lexicon" "^0.4.3"
|
"@atproto/lexicon" "^0.4.4"
|
||||||
"@atproto/repo" "^0.5.5"
|
"@atproto/repo" "^0.6.0"
|
||||||
"@atproto/sync" "^0.1.6"
|
"@atproto/sync" "^0.1.7"
|
||||||
"@atproto/syntax" "^0.3.1"
|
"@atproto/syntax" "^0.3.1"
|
||||||
"@atproto/xrpc-server" "^0.7.3"
|
"@atproto/xrpc-server" "^0.7.4"
|
||||||
"@bufbuild/protobuf" "^1.5.0"
|
"@bufbuild/protobuf" "^1.5.0"
|
||||||
"@connectrpc/connect" "^1.1.4"
|
"@connectrpc/connect" "^1.1.4"
|
||||||
"@connectrpc/connect-express" "^1.1.4"
|
"@connectrpc/connect-express" "^1.1.4"
|
||||||
@@ -129,12 +129,12 @@
|
|||||||
typed-emitter "^2.1.0"
|
typed-emitter "^2.1.0"
|
||||||
uint8arrays "3.0.0"
|
uint8arrays "3.0.0"
|
||||||
|
|
||||||
"@atproto/bsync@^0.0.9":
|
"@atproto/bsync@^0.0.10":
|
||||||
version "0.0.9"
|
version "0.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/bsync/-/bsync-0.0.9.tgz#7a6d58ef776404893d3c1139bdfe606fef483612"
|
resolved "https://registry.yarnpkg.com/@atproto/bsync/-/bsync-0.0.10.tgz#fa16acfaf67112449b703778a20c785226c94189"
|
||||||
integrity sha512-N0+TnYOoJz4hTo6/h1jJKh6QzdbwkFuOQ1bdwugzST7ZkwMtjs5FX8o/uqgiD4gSHSqfQSRrew7+qYEHUT61Aw==
|
integrity sha512-qviPMyYade/sqhX/9X9eTT4KaQ+FLvOyz+140LCDk/0vbZUCZPuYSEXZDCQkL5nlEXzScsQ3iyVeoYCGvV5kYw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/common" "^0.4.4"
|
"@atproto/common" "^0.4.5"
|
||||||
"@atproto/syntax" "^0.3.1"
|
"@atproto/syntax" "^0.3.1"
|
||||||
"@bufbuild/protobuf" "^1.5.0"
|
"@bufbuild/protobuf" "^1.5.0"
|
||||||
"@connectrpc/connect" "^1.1.4"
|
"@connectrpc/connect" "^1.1.4"
|
||||||
@@ -175,10 +175,10 @@
|
|||||||
pino "^8.6.1"
|
pino "^8.6.1"
|
||||||
zod "^3.14.2"
|
zod "^3.14.2"
|
||||||
|
|
||||||
"@atproto/common@^0.4.4":
|
"@atproto/common@^0.4.5":
|
||||||
version "0.4.4"
|
version "0.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.4.4.tgz#79096aef920f5ad7cda5c682d7ed7416d0581e1a"
|
resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.4.5.tgz#28fd176a9b5527c723828e725586bc0be9fa9516"
|
||||||
integrity sha512-58tMbn6A1Zu296s/l3uIj8z9d7IRHpZvLOfsFRikaQaYrzhJpL2aPY4uFQ8GJcxnsxeUnxBCrQz9we5jVVJI5Q==
|
integrity sha512-LFAGqHcxCI5+b31Xgk+VQQtZU258iGPpHJzNeHVcdh6teIKZi4C2l6YV+m+3CEz+yYcfP7jjUmgqesx7l9Arsg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/common-web" "^0.3.1"
|
"@atproto/common-web" "^0.3.1"
|
||||||
"@ipld/dag-cbor" "^7.0.3"
|
"@ipld/dag-cbor" "^7.0.3"
|
||||||
@@ -207,23 +207,23 @@
|
|||||||
"@noble/hashes" "^1.3.1"
|
"@noble/hashes" "^1.3.1"
|
||||||
uint8arrays "3.0.0"
|
uint8arrays "3.0.0"
|
||||||
|
|
||||||
"@atproto/dev-env@^0.3.64":
|
"@atproto/dev-env@^0.3.67":
|
||||||
version "0.3.64"
|
version "0.3.67"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/dev-env/-/dev-env-0.3.64.tgz#148537785b6a86b0a56d0988e63a1ff8ea7c84e9"
|
resolved "https://registry.yarnpkg.com/@atproto/dev-env/-/dev-env-0.3.67.tgz#4f6a20f0aafa8125ed9ec715abceedd11580882e"
|
||||||
integrity sha512-s7mdppgp2BS0uy5ASZwqJ3J8dez14pDGI9uqTGbsOYF/qTCbBGZKw/Vkqjci5bY1UaW+o6n787q63ECDtljM8A==
|
integrity sha512-7Ize4Y5vdjQjyrxTwjBPbkxKXQdE02KpE7AJLJt6Xpvowd2vbn8l8rDXfha+LtVi6t/613U4s+Slo5c1YD3x9A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/api" "^0.13.18"
|
"@atproto/api" "^0.13.20"
|
||||||
"@atproto/bsky" "^0.0.96"
|
"@atproto/bsky" "^0.0.98"
|
||||||
"@atproto/bsync" "^0.0.9"
|
"@atproto/bsync" "^0.0.10"
|
||||||
"@atproto/common-web" "^0.3.1"
|
"@atproto/common-web" "^0.3.1"
|
||||||
"@atproto/crypto" "^0.4.2"
|
"@atproto/crypto" "^0.4.2"
|
||||||
"@atproto/identity" "^0.4.3"
|
"@atproto/identity" "^0.4.3"
|
||||||
"@atproto/lexicon" "^0.4.3"
|
"@atproto/lexicon" "^0.4.4"
|
||||||
"@atproto/ozone" "^0.1.57"
|
"@atproto/ozone" "^0.1.59"
|
||||||
"@atproto/pds" "^0.4.73"
|
"@atproto/pds" "^0.4.76"
|
||||||
"@atproto/sync" "^0.1.6"
|
"@atproto/sync" "^0.1.7"
|
||||||
"@atproto/syntax" "^0.3.1"
|
"@atproto/syntax" "^0.3.1"
|
||||||
"@atproto/xrpc-server" "^0.7.3"
|
"@atproto/xrpc-server" "^0.7.4"
|
||||||
"@did-plc/lib" "^0.0.1"
|
"@did-plc/lib" "^0.0.1"
|
||||||
"@did-plc/server" "^0.0.1"
|
"@did-plc/server" "^0.0.1"
|
||||||
axios "^0.27.2"
|
axios "^0.27.2"
|
||||||
@@ -258,10 +258,10 @@
|
|||||||
multiformats "^9.9.0"
|
multiformats "^9.9.0"
|
||||||
zod "^3.23.8"
|
zod "^3.23.8"
|
||||||
|
|
||||||
"@atproto/lexicon@^0.4.3":
|
"@atproto/lexicon@^0.4.4":
|
||||||
version "0.4.3"
|
version "0.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.3.tgz#d69f6bb363a6326df7766c48132bfa30e22622d9"
|
resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.4.tgz#0d97314bb57b693b76f2495fa5e02872469dd93a"
|
||||||
integrity sha512-lFVZXe1S1pJP0dcxvJuHP3r/a+EAIBwwU7jUK+r8iLhIja+ml6NmYv8KeFHmIJATh03spEQ9s02duDmFVdCoXg==
|
integrity sha512-QFEmr3rpj/RoAmfX9ALU/asBG/rsVtQZnw+9nOB1/AuIwoxXd+ZyndR6lVUc2+DL4GEjl6W2yvBru5xbQIZWyA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/common-web" "^0.3.1"
|
"@atproto/common-web" "^0.3.1"
|
||||||
"@atproto/syntax" "^0.3.1"
|
"@atproto/syntax" "^0.3.1"
|
||||||
@@ -269,20 +269,20 @@
|
|||||||
multiformats "^9.9.0"
|
multiformats "^9.9.0"
|
||||||
zod "^3.23.8"
|
zod "^3.23.8"
|
||||||
|
|
||||||
"@atproto/oauth-provider@^0.2.7":
|
"@atproto/oauth-provider@^0.2.10":
|
||||||
version "0.2.7"
|
version "0.2.10"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider/-/oauth-provider-0.2.7.tgz#38a211c197ee1ce4e92a5b59a92f2e15fcacee0b"
|
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider/-/oauth-provider-0.2.10.tgz#f9820d7f82c33d3b74e81a75873f50e1e654b901"
|
||||||
integrity sha512-T/cEr7TGs36SqTW8JzLAt9EchumYY48zuI4rqoAepYT29eGpP37SxK+5X0+fQHOKJPKWUGlYocR9fDm4CdzAPQ==
|
integrity sha512-cF42lo0+Mj+Zq2RXwS2NxmobmtL7YL1vXlYcN6iKflZ8pQ5WvpR/cZKsKEZOT9cEBBTw5MARKTYxbr8CPDKlHg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto-labs/fetch" "0.1.1"
|
"@atproto-labs/fetch" "0.1.2"
|
||||||
"@atproto-labs/fetch-node" "0.1.3"
|
"@atproto-labs/fetch-node" "0.1.4"
|
||||||
"@atproto-labs/pipe" "0.1.0"
|
"@atproto-labs/pipe" "0.1.0"
|
||||||
"@atproto-labs/simple-store" "0.1.1"
|
"@atproto-labs/simple-store" "0.1.1"
|
||||||
"@atproto-labs/simple-store-memory" "0.1.1"
|
"@atproto-labs/simple-store-memory" "0.1.1"
|
||||||
"@atproto/common" "^0.4.4"
|
"@atproto/common" "^0.4.5"
|
||||||
"@atproto/jwk" "0.1.1"
|
"@atproto/jwk" "0.1.1"
|
||||||
"@atproto/jwk-jose" "0.1.2"
|
"@atproto/jwk-jose" "0.1.2"
|
||||||
"@atproto/oauth-types" "0.2.0"
|
"@atproto/oauth-types" "0.2.1"
|
||||||
"@hapi/accept" "^6.0.3"
|
"@hapi/accept" "^6.0.3"
|
||||||
"@hapi/bourne" "^3.0.0"
|
"@hapi/bourne" "^3.0.0"
|
||||||
"@hapi/content" "^6.0.0"
|
"@hapi/content" "^6.0.0"
|
||||||
@@ -294,27 +294,27 @@
|
|||||||
psl "^1.9.0"
|
psl "^1.9.0"
|
||||||
zod "^3.23.8"
|
zod "^3.23.8"
|
||||||
|
|
||||||
"@atproto/oauth-types@0.2.0":
|
"@atproto/oauth-types@0.2.1":
|
||||||
version "0.2.0"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/oauth-types/-/oauth-types-0.2.0.tgz#28bc861b56cba093e6c52603cec1d3d38cd2a1e7"
|
resolved "https://registry.yarnpkg.com/@atproto/oauth-types/-/oauth-types-0.2.1.tgz#a7ace557cc91817fcde6195f023e4e1838e4aef6"
|
||||||
integrity sha512-v/4ht6eRh0yOu2iuuWujZdnJBamPKimdy8k0Xan8cVZ+a2i83UkhIIU+S/XUbbvJ4a64wLPZrS9IDd0K5XYYTQ==
|
integrity sha512-hDisUXzcq5KU1HMuCYZ8Kcz7BePl7V11bFjjgZvND3mdSphiyBpJ8MCNn3QzAa6cXpFo0w9PDcYMAlCCRZHdVw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/jwk" "0.1.1"
|
"@atproto/jwk" "0.1.1"
|
||||||
zod "^3.23.8"
|
zod "^3.23.8"
|
||||||
|
|
||||||
"@atproto/ozone@^0.1.57":
|
"@atproto/ozone@^0.1.59":
|
||||||
version "0.1.57"
|
version "0.1.59"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.1.57.tgz#141d66b213710575c7859d691586fd44c731f7ca"
|
resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.1.59.tgz#219984a46617b0ac039f2f02767290eaa0b4cfc3"
|
||||||
integrity sha512-P2YKeRFPbxKc2e2yftUoMTTcWYuFV0qU1/Nkd4GxuHnBnDJcbtMPglXd7kyLf0p8plCCFau/wZ8QdY8KSDLM9Q==
|
integrity sha512-AD03Ocb3fZW+grxO/VwMld5iNdCLgbahFzku6xh1qEw0tLOBKp3GXSfepVd9XWu5fb1yPhGPd2JgjApV5hbJvw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/api" "^0.13.18"
|
"@atproto/api" "^0.13.20"
|
||||||
"@atproto/common" "^0.4.4"
|
"@atproto/common" "^0.4.5"
|
||||||
"@atproto/crypto" "^0.4.2"
|
"@atproto/crypto" "^0.4.2"
|
||||||
"@atproto/identity" "^0.4.3"
|
"@atproto/identity" "^0.4.3"
|
||||||
"@atproto/lexicon" "^0.4.3"
|
"@atproto/lexicon" "^0.4.4"
|
||||||
"@atproto/syntax" "^0.3.1"
|
"@atproto/syntax" "^0.3.1"
|
||||||
"@atproto/xrpc" "^0.6.4"
|
"@atproto/xrpc" "^0.6.5"
|
||||||
"@atproto/xrpc-server" "^0.7.3"
|
"@atproto/xrpc-server" "^0.7.4"
|
||||||
"@did-plc/lib" "^0.0.1"
|
"@did-plc/lib" "^0.0.1"
|
||||||
axios "^1.6.7"
|
axios "^1.6.7"
|
||||||
compression "^1.7.4"
|
compression "^1.7.4"
|
||||||
@@ -331,29 +331,30 @@
|
|||||||
typed-emitter "^2.1.0"
|
typed-emitter "^2.1.0"
|
||||||
uint8arrays "3.0.0"
|
uint8arrays "3.0.0"
|
||||||
|
|
||||||
"@atproto/pds@^0.4.73":
|
"@atproto/pds@^0.4.76":
|
||||||
version "0.4.73"
|
version "0.4.76"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/pds/-/pds-0.4.73.tgz#49b7625d9b40a5a24be1cdd7cdb56faab9e25707"
|
resolved "https://registry.yarnpkg.com/@atproto/pds/-/pds-0.4.76.tgz#cd7b3f13359a7c31dc9362a5e4309419512c4102"
|
||||||
integrity sha512-fzrKlgKVF5JvTTmhfvofXT9Ok1KFTfAjCzTrLJivbOcqQSqBagNTuz5CiQxAAAo/JTlSxmnyr3e7OrlJdrph1w==
|
integrity sha512-+cFVpqlgpCS0BuGac5fCQPZUugpS1r7ghnSQLVdjnTnvQJCqLRA++BlJWYbGgRP6FJrumCY2jtuwG8t59Rjt8Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto-labs/fetch-node" "0.1.3"
|
"@atproto-labs/fetch-node" "0.1.4"
|
||||||
"@atproto/api" "^0.13.18"
|
"@atproto/api" "^0.13.20"
|
||||||
"@atproto/aws" "^0.2.9"
|
"@atproto/aws" "^0.2.10"
|
||||||
"@atproto/common" "^0.4.4"
|
"@atproto/common" "^0.4.5"
|
||||||
"@atproto/crypto" "^0.4.2"
|
"@atproto/crypto" "^0.4.2"
|
||||||
"@atproto/identity" "^0.4.3"
|
"@atproto/identity" "^0.4.3"
|
||||||
"@atproto/lexicon" "^0.4.3"
|
"@atproto/lexicon" "^0.4.4"
|
||||||
"@atproto/oauth-provider" "^0.2.7"
|
"@atproto/oauth-provider" "^0.2.10"
|
||||||
"@atproto/repo" "^0.5.5"
|
"@atproto/repo" "^0.6.0"
|
||||||
"@atproto/syntax" "^0.3.1"
|
"@atproto/syntax" "^0.3.1"
|
||||||
"@atproto/xrpc" "^0.6.4"
|
"@atproto/xrpc" "^0.6.5"
|
||||||
"@atproto/xrpc-server" "^0.7.3"
|
"@atproto/xrpc-server" "^0.7.4"
|
||||||
"@did-plc/lib" "^0.0.4"
|
"@did-plc/lib" "^0.0.4"
|
||||||
|
"@hapi/address" "^5.1.1"
|
||||||
better-sqlite3 "^10.0.0"
|
better-sqlite3 "^10.0.0"
|
||||||
bytes "^3.1.2"
|
bytes "^3.1.2"
|
||||||
compression "^1.7.4"
|
compression "^1.7.4"
|
||||||
cors "^2.8.5"
|
cors "^2.8.5"
|
||||||
disposable-email "^0.2.3"
|
disposable-email-domains-js "^1.5.0"
|
||||||
express "^4.17.2"
|
express "^4.17.2"
|
||||||
express-async-errors "^3.1.1"
|
express-async-errors "^3.1.1"
|
||||||
file-type "^16.5.4"
|
file-type "^16.5.4"
|
||||||
@@ -376,49 +377,50 @@
|
|||||||
undici "^6.19.8"
|
undici "^6.19.8"
|
||||||
zod "^3.23.8"
|
zod "^3.23.8"
|
||||||
|
|
||||||
"@atproto/repo@^0.5.5":
|
"@atproto/repo@^0.6.0":
|
||||||
version "0.5.5"
|
version "0.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/repo/-/repo-0.5.5.tgz#73eaf1a0b35cfc4fc1c837f4e3ddeb6768d29c20"
|
resolved "https://registry.yarnpkg.com/@atproto/repo/-/repo-0.6.0.tgz#29e698731e6df63636b0f7c91ce106a9de50ad19"
|
||||||
integrity sha512-Zu1tw42KBVyFzIh1XYSIvm8V+V9oEKWJR7NnHBgeSMwCc9QwM32jO7uqgvEjZYEXgdYKanGhv/YHLyxtZa5Ckg==
|
integrity sha512-6YGVhjiHKmqCW5Ce4oY49E3NCEfbvAGowJ5ETXX2sx2l4D2bOL7a2hn5zWqsPHYpWSLjrPfnj7PVpApK0kmL7A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/common" "^0.4.4"
|
"@atproto/common" "^0.4.5"
|
||||||
"@atproto/common-web" "^0.3.1"
|
"@atproto/common-web" "^0.3.1"
|
||||||
"@atproto/crypto" "^0.4.2"
|
"@atproto/crypto" "^0.4.2"
|
||||||
"@atproto/lexicon" "^0.4.3"
|
"@atproto/lexicon" "^0.4.4"
|
||||||
"@ipld/car" "^3.2.3"
|
"@ipld/car" "^3.2.3"
|
||||||
"@ipld/dag-cbor" "^7.0.0"
|
"@ipld/dag-cbor" "^7.0.0"
|
||||||
multiformats "^9.9.0"
|
multiformats "^9.9.0"
|
||||||
uint8arrays "3.0.0"
|
uint8arrays "3.0.0"
|
||||||
zod "^3.23.8"
|
zod "^3.23.8"
|
||||||
|
|
||||||
"@atproto/sync@^0.1.6":
|
"@atproto/sync@^0.1.7":
|
||||||
version "0.1.6"
|
version "0.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/sync/-/sync-0.1.6.tgz#fb3e61147c05caf2c3d1cd597ff94fef68abbc02"
|
resolved "https://registry.yarnpkg.com/@atproto/sync/-/sync-0.1.7.tgz#c7f78d99bb40eacf93ca13fdd04134a0985bf421"
|
||||||
integrity sha512-9lqe6E6fIns28TJyQufLCVefMxmK3bvEfQBhmXJBGZMHuKlH8+F5P9DfnHv6vs6ygfmHIUIjYDWqJu/rpt8pzw==
|
integrity sha512-liJH2EsD4AbWA8G0oRDURgbHW6Uq4NnM2rNfbrTlqgtj0kyGRY3FcVEyqeRcaQYfCuscChIg5DQKHqY421/7Mw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/common" "^0.4.4"
|
"@atproto/common" "^0.4.5"
|
||||||
"@atproto/identity" "^0.4.3"
|
"@atproto/identity" "^0.4.3"
|
||||||
"@atproto/lexicon" "^0.4.3"
|
"@atproto/lexicon" "^0.4.4"
|
||||||
"@atproto/repo" "^0.5.5"
|
"@atproto/repo" "^0.6.0"
|
||||||
"@atproto/syntax" "^0.3.1"
|
"@atproto/syntax" "^0.3.1"
|
||||||
"@atproto/xrpc-server" "^0.7.3"
|
"@atproto/xrpc-server" "^0.7.4"
|
||||||
multiformats "^9.9.0"
|
multiformats "^9.9.0"
|
||||||
p-queue "^6.6.2"
|
p-queue "^6.6.2"
|
||||||
|
ws "^8.12.0"
|
||||||
|
|
||||||
"@atproto/syntax@^0.3.1":
|
"@atproto/syntax@^0.3.1":
|
||||||
version "0.3.1"
|
version "0.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.3.1.tgz#4346418728f9643d783d2ffcf7c77e132e1f53d4"
|
resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.3.1.tgz#4346418728f9643d783d2ffcf7c77e132e1f53d4"
|
||||||
integrity sha512-fzW0Mg1QUOVCWUD3RgEsDt6d1OZ6DdFmbKcDdbzUfh0t4rhtRAC05KbZYmxuMPWDAiJ4BbbQ5dkAc/mNypMXkw==
|
integrity sha512-fzW0Mg1QUOVCWUD3RgEsDt6d1OZ6DdFmbKcDdbzUfh0t4rhtRAC05KbZYmxuMPWDAiJ4BbbQ5dkAc/mNypMXkw==
|
||||||
|
|
||||||
"@atproto/xrpc-server@^0.7.3":
|
"@atproto/xrpc-server@^0.7.4":
|
||||||
version "0.7.3"
|
version "0.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/xrpc-server/-/xrpc-server-0.7.3.tgz#d09b36d00edb7aacca48675d1ebb7fa796fa11bd"
|
resolved "https://registry.yarnpkg.com/@atproto/xrpc-server/-/xrpc-server-0.7.4.tgz#dfac8f7276c1c971a35eaba627eb6372088441c3"
|
||||||
integrity sha512-x0qegkN6snrbXJO3v9h2kuh9e90g6ZZkDXv3COiraGS3yRTzIm6i4bMvDSfCI50+0xCNtPKOkpn8taRoRgkyiw==
|
integrity sha512-MrAwxfJBQm/kCol3D8qc+vpQzBMzLqvtUbauSSfVVJ10PlGtxg4LlXqcjkAuhrjyrqp3dQH9LHuhDpgVQK+G3w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/common" "^0.4.4"
|
"@atproto/common" "^0.4.5"
|
||||||
"@atproto/crypto" "^0.4.2"
|
"@atproto/crypto" "^0.4.2"
|
||||||
"@atproto/lexicon" "^0.4.3"
|
"@atproto/lexicon" "^0.4.4"
|
||||||
"@atproto/xrpc" "^0.6.4"
|
"@atproto/xrpc" "^0.6.5"
|
||||||
cbor-x "^1.5.1"
|
cbor-x "^1.5.1"
|
||||||
express "^4.17.2"
|
express "^4.17.2"
|
||||||
http-errors "^2.0.0"
|
http-errors "^2.0.0"
|
||||||
@@ -428,12 +430,12 @@
|
|||||||
ws "^8.12.0"
|
ws "^8.12.0"
|
||||||
zod "^3.23.8"
|
zod "^3.23.8"
|
||||||
|
|
||||||
"@atproto/xrpc@^0.6.4":
|
"@atproto/xrpc@^0.6.5":
|
||||||
version "0.6.4"
|
version "0.6.5"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.4.tgz#4cf59774f7c72e5bc821bc5f1d57f0a6ae2014db"
|
resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.5.tgz#8b180fc5f6b8374fd00c41b9e4cd7b24ead48e6b"
|
||||||
integrity sha512-9ZAJ8nsXTqC4XFyS0E1Wlg7bAvonhXQNQ3Ocs1L1LIwFLXvsw/4fNpIHXxvXvqTCVeyHLbImOnE9UiO1c/qIYA==
|
integrity sha512-t6u8iPEVbWge5RhzKZDahSzNDYIAxUtop6Q/X/apAZY1rgreVU0/1sSvvRoRFH19d3UIKjYdLuwFqMi9w8nY3Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/lexicon" "^0.4.3"
|
"@atproto/lexicon" "^0.4.4"
|
||||||
zod "^3.23.8"
|
zod "^3.23.8"
|
||||||
|
|
||||||
"@aws-crypto/crc32@3.0.0":
|
"@aws-crypto/crc32@3.0.0":
|
||||||
@@ -4378,6 +4380,13 @@
|
|||||||
"@hapi/boom" "^10.0.1"
|
"@hapi/boom" "^10.0.1"
|
||||||
"@hapi/hoek" "^11.0.2"
|
"@hapi/hoek" "^11.0.2"
|
||||||
|
|
||||||
|
"@hapi/address@^5.1.1":
|
||||||
|
version "5.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-5.1.1.tgz#e9925fc1b65f5cc3fbea821f2b980e4652e84cb6"
|
||||||
|
integrity sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==
|
||||||
|
dependencies:
|
||||||
|
"@hapi/hoek" "^11.0.2"
|
||||||
|
|
||||||
"@hapi/boom@^10.0.0", "@hapi/boom@^10.0.1":
|
"@hapi/boom@^10.0.0", "@hapi/boom@^10.0.1":
|
||||||
version "10.0.1"
|
version "10.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-10.0.1.tgz#ebb14688275ae150aa6af788dbe482e6a6062685"
|
resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-10.0.1.tgz#ebb14688275ae150aa6af788dbe482e6a6062685"
|
||||||
@@ -9593,10 +9602,10 @@ dir-glob@^3.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
path-type "^4.0.0"
|
path-type "^4.0.0"
|
||||||
|
|
||||||
disposable-email@^0.2.3:
|
disposable-email-domains-js@^1.5.0:
|
||||||
version "0.2.3"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/disposable-email/-/disposable-email-0.2.3.tgz#a21a49717f6034a8ff777dc8eae3b4d994a7b988"
|
resolved "https://registry.yarnpkg.com/disposable-email-domains-js/-/disposable-email-domains-js-1.7.0.tgz#2bf859bccf7a2eb697025577e18f0434409713ec"
|
||||||
integrity sha512-gkBQQ5Res431ZXqLlAafrXHizG7/1FWmi8U2RTtriD78Vc10HhBUvdJun3R4eSF0KRIQQJs+wHlxjkED/Hr1EQ==
|
integrity sha512-qcIJcnXjDvH8EEt0tyAesk1sZVGU5ZFtW6Wys2wKCAcbUf5nJYfwZfT7Z0PVA/LBMlqd/Xgk9dXN2Q3fx7NFAg==
|
||||||
|
|
||||||
dns-equal@^1.0.0:
|
dns-equal@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user