Trigger a notifee card on new notifications

This commit is contained in:
Paul Frazee
2023-01-24 19:13:47 -06:00
parent eccb2589c5
commit 495227bb2c
6 changed files with 73 additions and 5 deletions
+1 -1
View File
@@ -587,7 +587,7 @@ export const mockedMeStore = {
clear: jest.fn(),
load: jest.fn(),
clearNotificationCount: jest.fn(),
fetchStateUpdate: jest.fn(),
fetchNotifications: jest.fn(),
refreshMemberships: jest.fn(),
} as MeModel
+1 -1
View File
@@ -173,7 +173,7 @@ describe('MeModel', () => {
})
})
await meModel.fetchStateUpdate()
await meModel.fetchNotifications()
expect(meModel.notificationCount).toBe(1)
expect(meModel.notifications.refresh).toHaveBeenCalled()
})
+8
View File
@@ -16,6 +16,7 @@ import * as view from './view/index'
import {RootStoreModel, setupState, RootStoreProvider} from './state'
import {MobileShell} from './view/shell/mobile'
import {s} from './view/lib/styles'
import notifee, {EventType} from '@notifee/react-native'
const App = observer(() => {
const [rootStore, setRootStore] = useState<RootStoreModel | undefined>(
@@ -43,6 +44,13 @@ const App = observer(() => {
Linking.addEventListener('url', ({url}) => {
store.nav.handleLink(url)
})
notifee.onForegroundEvent(async ({type}: {type: EventType}) => {
store.log.debug('Notifee foreground event', {type})
if (type === EventType.PRESS) {
store.log.debug('User pressed a notifee, opening notifications')
store.nav.switchTo(1, true)
}
})
})
}, [])
+12 -2
View File
@@ -118,7 +118,7 @@ export class MeModel {
notifee.setBadgeCount(0)
}
async fetchStateUpdate() {
async fetchNotifications() {
const res = await this.rootStore.api.app.bsky.notification.getCount()
runInAction(() => {
const newNotifications = this.notificationCount !== res.data.count
@@ -126,7 +126,17 @@ export class MeModel {
notifee.setBadgeCount(this.notificationCount)
if (newNotifications) {
// trigger pre-emptive fetch on new notifications
this.notifications.refresh()
let oldMostRecent = this.notifications.mostRecentNotification
this.notifications.refresh().then(() => {
// if a new most recent notification is found, trigger a notification card
const mostRecent = this.notifications.mostRecentNotification
if (mostRecent && oldMostRecent?.uri !== mostRecent?.uri) {
const notifeeOpts = mostRecent.toNotifeeOpts()
if (notifeeOpts) {
notifee.displayNotification(notifeeOpts)
}
}
})
}
})
}
+50
View File
@@ -7,6 +7,7 @@ import {
AppBskyFeedVote,
AppBskyGraphAssertion,
AppBskyGraphFollow,
AppBskyEmbedImages,
} from '@atproto/api'
import {RootStoreModel} from './root-store'
import {PostThreadViewModel} from './post-thread-view'
@@ -179,6 +180,42 @@ export class NotificationsViewItemModel {
})
}
}
toNotifeeOpts() {
let author = this.author.displayName || this.author.handle
let title: string
let body: string = ''
if (this.isUpvote) {
title = `${author} liked your post`
body = this.additionalPost?.thread?.postRecord?.text || ''
} else if (this.isRepost) {
title = `${author} reposted your post`
body = this.additionalPost?.thread?.postRecord?.text || ''
} else if (this.isReply) {
title = `${author} replied to your post`
body = this.additionalPost?.thread?.postRecord?.text || ''
} else if (this.isFollow) {
title = `${author} followed you`
} else {
return undefined
}
let ios
if (
AppBskyEmbedImages.isPresented(this.additionalPost?.thread?.post.embed) &&
this.additionalPost?.thread?.post.embed.images[0]?.thumb
) {
ios = {
attachments: [
{url: this.additionalPost.thread.post.embed.images[0].thumb},
],
}
}
return {
title,
body,
ios,
}
}
}
export class NotificationsViewModel {
@@ -197,6 +234,9 @@ export class NotificationsViewModel {
// data
notifications: NotificationsViewItemModel[] = []
// this is used to trigger push notifications
mostRecentNotification: NotificationsViewItemModel | undefined
constructor(
public rootStore: RootStoreModel,
params: ListNotifications.QueryParams,
@@ -388,6 +428,16 @@ export class NotificationsViewModel {
}
private async _replaceAll(res: ListNotifications.Response) {
if (res.data.notifications[0]) {
this.mostRecentNotification = new NotificationsViewItemModel(
this.rootStore,
'mostRecent',
res.data.notifications[0],
)
await this.mostRecentNotification.fetchAdditionalData()
} else {
this.mostRecentNotification = undefined
}
return this._appendAll(res, true)
}
+1 -1
View File
@@ -55,7 +55,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