Activity notification settings (#8485)
Co-authored-by: Eric Bailey <git@esb.lol> Co-authored-by: Samuel Newman <mozzius@protonmail.com> Co-authored-by: hailey <me@haileyok.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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: [],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 !== '') {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user