[APP-786] Native notifications (#1095)
* move `notifee.ts` to notifications folder * install expo notifications * add UIBackgroundMode `remote-notifications` to app.json * fix notifee import in Debug.tsx * add `google-services.json` * add `development-device` class to eas.json * Add `notifications.ts` for native notification handling * send push token to server * update `@atproto/api` * fix putting notif token to server * fix how push token is uploaded * fix lint * enable debug appview proxy header on all platforms * setup `notifications.ts` to work with app view notifs * clean up notification handler * add comments * update packages to correct versions * remove notifee * clean up code a lil * rename push token endpoint * remove unnecessary comments * fix comments * Remove old background scheduler * Fixes to push notifications API use * Bump @atproto/api@0.6.6 --------- Co-authored-by: Paul Frazee <pfrazee@gmail.com>
This commit is contained in:
parent
32b9648931
commit
8ab5eb6583
18 changed files with 253 additions and 260 deletions
|
@ -478,36 +478,6 @@ export class NotificationsFeedModel {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in background fetch to trigger notifications
|
||||
*/
|
||||
async getNewMostRecent(): Promise<NotificationsFeedItemModel | undefined> {
|
||||
let old = this.mostRecentNotificationUri
|
||||
const res = await this.rootStore.agent.listNotifications({
|
||||
limit: 1,
|
||||
})
|
||||
if (!res.data.notifications[0] || old === res.data.notifications[0].uri) {
|
||||
return
|
||||
}
|
||||
this.mostRecentNotificationUri = res.data.notifications[0].uri
|
||||
const notif = new NotificationsFeedItemModel(
|
||||
this.rootStore,
|
||||
'mostRecent',
|
||||
res.data.notifications[0],
|
||||
)
|
||||
const addedUri = notif.additionalDataUri
|
||||
if (addedUri) {
|
||||
const postsRes = await this.rootStore.agent.app.bsky.feed.getPosts({
|
||||
uris: [addedUri],
|
||||
})
|
||||
const post = postsRes.data.posts[0]
|
||||
notif.setAdditionalData(post)
|
||||
this.rootStore.posts.set(post.uri, post)
|
||||
}
|
||||
const filtered = this._filterNotifications([notif])
|
||||
return filtered[0]
|
||||
}
|
||||
|
||||
// state transitions
|
||||
// =
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import {makeAutoObservable} from 'mobx'
|
|||
import {BskyAgent} from '@atproto/api'
|
||||
import {createContext, useContext} from 'react'
|
||||
import {DeviceEventEmitter, EmitterSubscription} from 'react-native'
|
||||
import * as BgScheduler from 'lib/bg-scheduler'
|
||||
import {z} from 'zod'
|
||||
import {isObj, hasProp} from 'lib/type-guards'
|
||||
import {LogModel} from './log'
|
||||
|
@ -16,7 +15,6 @@ import {HandleResolutionsCache} from './cache/handle-resolutions'
|
|||
import {ProfilesCache} from './cache/profiles-view'
|
||||
import {PostsCache} from './cache/posts'
|
||||
import {LinkMetasCache} from './cache/link-metas'
|
||||
import {NotificationsFeedItemModel} from './feeds/notifications'
|
||||
import {MeModel} from './me'
|
||||
import {InvitedUsers} from './invited-users'
|
||||
import {PreferencesModel} from './ui/preferences'
|
||||
|
@ -61,7 +59,6 @@ export class RootStoreModel {
|
|||
serialize: false,
|
||||
hydrate: false,
|
||||
})
|
||||
this.initBgFetch()
|
||||
}
|
||||
|
||||
setAppInfo(info: AppInfo) {
|
||||
|
@ -249,62 +246,6 @@ export class RootStoreModel {
|
|||
emitUnreadNotifications(count: number) {
|
||||
DeviceEventEmitter.emit('unread-notifications', count)
|
||||
}
|
||||
|
||||
// a notification has been queued for push
|
||||
onPushNotification(
|
||||
handler: (notif: NotificationsFeedItemModel) => void,
|
||||
): EmitterSubscription {
|
||||
return DeviceEventEmitter.addListener('push-notification', handler)
|
||||
}
|
||||
emitPushNotification(notif: NotificationsFeedItemModel) {
|
||||
DeviceEventEmitter.emit('push-notification', notif)
|
||||
}
|
||||
|
||||
// background fetch
|
||||
// =
|
||||
// - we use this to poll for unread notifications, which is not "ideal" behavior but
|
||||
// gives us a solution for push-notifications that work against any pds
|
||||
|
||||
initBgFetch() {
|
||||
// NOTE
|
||||
// background fetch runs every 15 minutes *at most* and will get slowed down
|
||||
// based on some heuristics run by iOS, meaning it is not a reliable form of delivery
|
||||
// -prf
|
||||
BgScheduler.configure(
|
||||
this.onBgFetch.bind(this),
|
||||
this.onBgFetchTimeout.bind(this),
|
||||
).then(status => {
|
||||
this.log.debug(`Background fetch initiated, status: ${status}`)
|
||||
})
|
||||
}
|
||||
|
||||
async onBgFetch(taskId: string) {
|
||||
this.log.debug(`Background fetch fired for task ${taskId}`)
|
||||
if (this.session.hasSession) {
|
||||
const res = await this.agent.countUnreadNotifications()
|
||||
const hasNewNotifs = this.me.notifications.unreadCount !== res.data.count
|
||||
this.emitUnreadNotifications(res.data.count)
|
||||
this.log.debug(
|
||||
`Background fetch received unread count = ${res.data.count}`,
|
||||
)
|
||||
if (hasNewNotifs) {
|
||||
this.log.debug(
|
||||
'Background fetch detected potentially a new notification',
|
||||
)
|
||||
const mostRecent = await this.me.notifications.getNewMostRecent()
|
||||
if (mostRecent) {
|
||||
this.log.debug('Got the notification, triggering a push')
|
||||
this.emitPushNotification(mostRecent)
|
||||
}
|
||||
}
|
||||
}
|
||||
BgScheduler.finish(taskId)
|
||||
}
|
||||
|
||||
onBgFetchTimeout(taskId: string) {
|
||||
this.log.debug(`Background fetch timed out for task ${taskId}`)
|
||||
BgScheduler.finish(taskId)
|
||||
}
|
||||
}
|
||||
|
||||
const throwawayInst = new RootStoreModel(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue