diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/api/feed/list.ts | 12 | ||||
-rw-r--r-- | src/lib/api/feed/posts.ts | 52 | ||||
-rw-r--r-- | src/lib/hooks/useNotificationHandler.ts | 44 | ||||
-rw-r--r-- | src/lib/moderation/create-sanitized-display-name.ts | 7 | ||||
-rw-r--r-- | src/lib/routes/types.ts | 2 | ||||
-rw-r--r-- | src/lib/statsig/gates.ts | 1 |
6 files changed, 97 insertions, 21 deletions
diff --git a/src/lib/api/feed/list.ts b/src/lib/api/feed/list.ts index 9744e3d4c..9697b0aaf 100644 --- a/src/lib/api/feed/list.ts +++ b/src/lib/api/feed/list.ts @@ -1,20 +1,20 @@ import { - AppBskyFeedDefs, - AppBskyFeedGetListFeed as GetListFeed, - BskyAgent, + type Agent, + type AppBskyFeedDefs, + type AppBskyFeedGetListFeed as GetListFeed, } from '@atproto/api' -import {FeedAPI, FeedAPIResponse} from './types' +import {type FeedAPI, type FeedAPIResponse} from './types' export class ListFeedAPI implements FeedAPI { - agent: BskyAgent + agent: Agent params: GetListFeed.QueryParams constructor({ agent, feedParams, }: { - agent: BskyAgent + agent: Agent feedParams: GetListFeed.QueryParams }) { this.agent = agent diff --git a/src/lib/api/feed/posts.ts b/src/lib/api/feed/posts.ts new file mode 100644 index 000000000..33eff5099 --- /dev/null +++ b/src/lib/api/feed/posts.ts @@ -0,0 +1,52 @@ +import { + type Agent, + type AppBskyFeedDefs, + type AppBskyFeedGetPosts, +} from '@atproto/api' + +import {logger} from '#/logger' +import {type FeedAPI, type FeedAPIResponse} from './types' + +export class PostListFeedAPI implements FeedAPI { + agent: Agent + params: AppBskyFeedGetPosts.QueryParams + peek: AppBskyFeedDefs.FeedViewPost | null = null + + constructor({ + agent, + feedParams, + }: { + agent: Agent + feedParams: AppBskyFeedGetPosts.QueryParams + }) { + this.agent = agent + if (feedParams.uris.length > 25) { + logger.warn( + `Too many URIs provided - expected 25, got ${feedParams.uris.length}`, + ) + } + this.params = { + uris: feedParams.uris.slice(0, 25), + } + } + + async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> { + if (this.peek) return this.peek + throw new Error('Has not fetched yet') + } + + async fetch({}: {}): Promise<FeedAPIResponse> { + const res = await this.agent.app.bsky.feed.getPosts({ + ...this.params, + }) + if (res.success) { + this.peek = {post: res.data.posts[0]} + return { + feed: res.data.posts.map(post => ({post})), + } + } + return { + feed: [], + } + } +} diff --git a/src/lib/hooks/useNotificationHandler.ts b/src/lib/hooks/useNotificationHandler.ts index 311f38a79..6c3e7deb8 100644 --- a/src/lib/hooks/useNotificationHandler.ts +++ b/src/lib/hooks/useNotificationHandler.ts @@ -1,6 +1,6 @@ import {useEffect} from 'react' import * as Notifications from 'expo-notifications' -import {type AppBskyNotificationListNotifications} from '@atproto/api' +import {AtUri} from '@atproto/api' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {CommonActions, useNavigation} from '@react-navigation/native' @@ -32,6 +32,7 @@ export type NotificationReason = | 'repost-via-repost' | 'verified' | 'unverified' + | 'subscribed-post' /** * Manually overridden type, but retains the possibility of @@ -112,61 +113,68 @@ export function useNotificationsHandler() { }) Notifications.setNotificationChannelAsync( - 'like' satisfies AppBskyNotificationListNotifications.Notification['reason'], + 'like' satisfies NotificationReason, { name: _(msg`Likes`), importance: Notifications.AndroidImportance.HIGH, }, ) Notifications.setNotificationChannelAsync( - 'repost' satisfies AppBskyNotificationListNotifications.Notification['reason'], + 'repost' satisfies NotificationReason, { name: _(msg`Reposts`), importance: Notifications.AndroidImportance.HIGH, }, ) Notifications.setNotificationChannelAsync( - 'reply' satisfies AppBskyNotificationListNotifications.Notification['reason'], + 'reply' satisfies NotificationReason, { name: _(msg`Replies`), importance: Notifications.AndroidImportance.HIGH, }, ) Notifications.setNotificationChannelAsync( - 'mention' satisfies AppBskyNotificationListNotifications.Notification['reason'], + 'mention' satisfies NotificationReason, { name: _(msg`Mentions`), importance: Notifications.AndroidImportance.HIGH, }, ) Notifications.setNotificationChannelAsync( - 'quote' satisfies AppBskyNotificationListNotifications.Notification['reason'], + 'quote' satisfies NotificationReason, { name: _(msg`Quotes`), importance: Notifications.AndroidImportance.HIGH, }, ) Notifications.setNotificationChannelAsync( - 'follow' satisfies AppBskyNotificationListNotifications.Notification['reason'], + 'follow' satisfies NotificationReason, { name: _(msg`New followers`), importance: Notifications.AndroidImportance.HIGH, }, ) Notifications.setNotificationChannelAsync( - 'like-via-repost' satisfies AppBskyNotificationListNotifications.Notification['reason'], + 'like-via-repost' satisfies NotificationReason, { name: _(msg`Likes of your reposts`), importance: Notifications.AndroidImportance.HIGH, }, ) Notifications.setNotificationChannelAsync( - 'repost-via-repost' satisfies AppBskyNotificationListNotifications.Notification['reason'], + 'repost-via-repost' satisfies NotificationReason, { name: _(msg`Reposts of your reposts`), importance: Notifications.AndroidImportance.HIGH, }, ) + Notifications.setNotificationChannelAsync( + 'subscribed-post' satisfies NotificationReason, + { + name: _(msg`Activity from others`), + importance: Notifications.AndroidImportance.HIGH, + }, + ) }, [_]) useEffect(() => { @@ -220,6 +228,23 @@ export function useNotificationsHandler() { } } else { switch (payload.reason) { + case 'subscribed-post': + const urip = new AtUri(payload.uri) + if (urip.collection === 'app.bsky.feed.post') { + setTimeout(() => { + // @ts-expect-error types are weird here + navigation.navigate('HomeTab', { + screen: 'PostThread', + params: { + name: urip.host, + rkey: urip.rkey, + }, + }) + }, 500) + } else { + resetToTab('NotificationsTab') + } + break case 'like': case 'repost': case 'follow': @@ -231,6 +256,7 @@ export function useNotificationsHandler() { case 'repost-via-repost': case 'verified': case 'unverified': + default: resetToTab('NotificationsTab') break // TODO implement these after we have an idea of how to handle each individual case diff --git a/src/lib/moderation/create-sanitized-display-name.ts b/src/lib/moderation/create-sanitized-display-name.ts index 4f9584f91..4c62a5c03 100644 --- a/src/lib/moderation/create-sanitized-display-name.ts +++ b/src/lib/moderation/create-sanitized-display-name.ts @@ -1,12 +1,9 @@ -import {AppBskyActorDefs} from '@atproto/api' - import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' +import type * as bsky from '#/types/bsky' export function createSanitizedDisplayName( - profile: - | AppBskyActorDefs.ProfileViewBasic - | AppBskyActorDefs.ProfileViewDetailed, + profile: bsky.profile.AnyProfileView, noAt = false, ) { if (profile.displayName != null && profile.displayName !== '') { diff --git a/src/lib/routes/types.ts b/src/lib/routes/types.ts index c92be34c2..b1db5caa6 100644 --- a/src/lib/routes/types.ts +++ b/src/lib/routes/types.ts @@ -51,6 +51,7 @@ export type CommonNavigatorParams = { AppearanceSettings: undefined AccountSettings: undefined PrivacyAndSecuritySettings: undefined + ActivityPrivacySettings: undefined ContentAndMediaSettings: undefined NotificationSettings: undefined ReplyNotificationSettings: undefined @@ -72,6 +73,7 @@ export type CommonNavigatorParams = { MessagesConversation: {conversation: string; embed?: string; accept?: true} MessagesSettings: undefined MessagesInbox: undefined + NotificationsActivityList: {posts: string} LegacyNotificationSettings: undefined Feeds: undefined Start: {name: string; rkey: string} diff --git a/src/lib/statsig/gates.ts b/src/lib/statsig/gates.ts index fca3f609a..3b1106480 100644 --- a/src/lib/statsig/gates.ts +++ b/src/lib/statsig/gates.ts @@ -7,7 +7,6 @@ export type Gate = | 'old_postonboarding' | 'onboarding_add_video_feed' | 'post_threads_v2_unspecced' - | 'reengagement_features' | 'remove_show_latest_button' | 'test_gate_1' | 'test_gate_2' |