Initial pass at push notifications + some fixes to the session management (#91)

* Fix: test the session during resume to ensure it's valid

* Don't delete sessions for now

* Add notifee and request notif permissions on first login

* Set unread notifications badge on app icon

* Trigger a notifee card on new notifications

* Experimental: use react-native-background-fetch to check for notifications

* Add missing mocks

* Fix to resumeSession()
This commit is contained in:
Paul Frazee 2023-01-24 19:32:24 -06:00 committed by GitHub
parent 21f5f4de15
commit 869f6c4e0e
12 changed files with 189 additions and 27 deletions

View file

@ -6,6 +6,7 @@ import {makeAutoObservable} from 'mobx'
import {sessionClient as AtpApi, SessionServiceClient} from '@atproto/api'
import {createContext, useContext} from 'react'
import {DeviceEventEmitter, EmitterSubscription} from 'react-native'
import BackgroundFetch from 'react-native-background-fetch'
import {isObj, hasProp} from '../lib/type-guards'
import {LogModel} from './log'
import {SessionModel} from './session'
@ -34,6 +35,7 @@ export class RootStoreModel {
serialize: false,
hydrate: false,
})
this.initBgFetch()
}
async resolveName(didOrHandle: string) {
@ -55,7 +57,7 @@ export class RootStoreModel {
if (!this.session.online) {
await this.session.connect()
}
await this.me.fetchStateUpdate()
await this.me.fetchNotifications()
} catch (e: any) {
if (isNetworkError(e)) {
this.session.setOnline(false) // connection lost
@ -109,9 +111,41 @@ export class RootStoreModel {
}
emitPostDeleted(uri: string) {
console.log('emit')
DeviceEventEmitter.emit('post-deleted', uri)
}
// 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
BackgroundFetch.configure(
{minimumFetchInterval: 15},
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) {
// grab notifications
await this.me.fetchNotifications()
}
BackgroundFetch.finish(taskId)
}
onBgFetchTimeout(taskId: string) {
this.log.debug(`Background fetch timed out for task ${taskId}`)
BackgroundFetch.finish(taskId)
}
}
const throwawayInst = new RootStoreModel(AtpApi.service('http://localhost')) // this will be replaced by the loader, we just need to supply a value at init