diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/state/models/me.ts | 15 | ||||
-rw-r--r-- | src/state/models/notifications-view.ts | 37 | ||||
-rw-r--r-- | src/view/com/notifications/Feed.tsx | 6 | ||||
-rw-r--r-- | src/view/screens/Notifications.tsx | 32 |
4 files changed, 49 insertions, 41 deletions
diff --git a/src/state/models/me.ts b/src/state/models/me.ts index 78c6d2e76..e3405b80d 100644 --- a/src/state/models/me.ts +++ b/src/state/models/me.ts @@ -1,6 +1,7 @@ import {makeAutoObservable, runInAction} from 'mobx' import {RootStoreModel} from './root-store' import {MembershipsViewModel} from './memberships-view' +import {NotificationsViewModel} from './notifications-view' export class MeModel { did?: string @@ -9,9 +10,11 @@ export class MeModel { description?: string notificationCount: number = 0 memberships?: MembershipsViewModel + notifications: NotificationsViewModel constructor(public rootStore: RootStoreModel) { makeAutoObservable(this, {rootStore: false}, {autoBind: true}) + this.notifications = new NotificationsViewModel(this.rootStore, {}) } clear() { @@ -43,7 +46,12 @@ export class MeModel { this.memberships = new MembershipsViewModel(this.rootStore, { actor: this.did, }) - await this.memberships?.setup() + await this.memberships?.setup().catch(e => { + console.error('Failed to setup memberships model', e) + }) + await this.notifications.setup().catch(e => { + console.error('Failed to setup notifications model', e) + }) } else { this.clear() } @@ -56,7 +64,12 @@ export class MeModel { async fetchStateUpdate() { const res = await this.rootStore.api.app.bsky.notification.getCount() runInAction(() => { + const newNotifications = this.notificationCount !== res.data.count this.notificationCount = res.data.count + if (newNotifications) { + // trigger pre-emptive fetch on new notifications + this.notifications.refresh() + } }) } diff --git a/src/state/models/notifications-view.ts b/src/state/models/notifications-view.ts index f3163822e..e81f31a25 100644 --- a/src/state/models/notifications-view.ts +++ b/src/state/models/notifications-view.ts @@ -203,7 +203,6 @@ export class NotificationsViewModel { await this._pendingWork() this._loadPromise = this._initialLoad(isRefreshing) await this._loadPromise - this._updateReadState() this._loadPromise = undefined } @@ -240,6 +239,20 @@ export class NotificationsViewModel { this._updatePromise = undefined } + /** + * Update read/unread state + */ + async updateReadState() { + try { + await this.rootStore.api.app.bsky.notification.updateSeen({ + seenAt: new Date().toISOString(), + }) + this.rootStore.me.clearNotificationCount() + } catch (e) { + console.log('Failed to update notifications read state', e) + } + } + // state transitions // = @@ -329,11 +342,10 @@ export class NotificationsViewModel { } private async _replaceAll(res: ListNotifications.Response) { - this.notifications.length = 0 - return this._appendAll(res) + return this._appendAll(res, true) } - private async _appendAll(res: ListNotifications.Response) { + private async _appendAll(res: ListNotifications.Response, replace = false) { this.loadMoreCursor = res.data.cursor this.hasMore = !!this.loadMoreCursor let counter = this.notifications.length @@ -357,7 +369,11 @@ export class NotificationsViewModel { ) }) runInAction(() => { - this.notifications = this.notifications.concat(itemModels) + if (replace) { + this.notifications = itemModels + } else { + this.notifications = this.notifications.concat(itemModels) + } }) } @@ -374,17 +390,6 @@ export class NotificationsViewModel { } } } - - private async _updateReadState() { - try { - await this.rootStore.api.app.bsky.notification.updateSeen({ - seenAt: new Date().toISOString(), - }) - this.rootStore.me.clearNotificationCount() - } catch (e) { - console.log('Failed to update notifications read state', e) - } - } } function groupNotifications( diff --git a/src/view/com/notifications/Feed.tsx b/src/view/com/notifications/Feed.tsx index 90d16604d..78dcd2fa8 100644 --- a/src/view/com/notifications/Feed.tsx +++ b/src/view/com/notifications/Feed.tsx @@ -32,7 +32,7 @@ export const Feed = observer(function Feed({ } return ( <View style={{flex: 1}}> - {view.isLoading && !view.isRefreshing && !view.hasContent && ( + {view.isLoading && !view.isRefreshing && ( <NotificationFeedLoadingPlaceholder /> )} {view.hasError && ( @@ -43,7 +43,7 @@ export const Feed = observer(function Feed({ onPressTryAgain={onPressTryAgain} /> )} - {view.hasContent && ( + {view.hasLoaded && ( <FlatList data={view.notifications} keyExtractor={item => item._reactKey} @@ -53,7 +53,7 @@ export const Feed = observer(function Feed({ onEndReached={onEndReached} /> )} - {view.isEmpty && ( + {view.hasLoaded && view.isEmpty && ( <EmptyState icon="bell" message="No notifications yet!" /> )} </View> diff --git a/src/view/screens/Notifications.tsx b/src/view/screens/Notifications.tsx index 1e7abdb90..b168ffaff 100644 --- a/src/view/screens/Notifications.tsx +++ b/src/view/screens/Notifications.tsx @@ -7,43 +7,33 @@ import {NotificationsViewModel} from '../../state/models/notifications-view' import {ScreenParams} from '../routes' export const Notifications = ({navIdx, visible}: ScreenParams) => { - const [hasSetup, setHasSetup] = useState<boolean>(false) - const [notesView, setNotesView] = useState< - NotificationsViewModel | undefined - >() const store = useStores() useEffect(() => { - let aborted = false if (!visible) { return } + console.log('Updating notifications feed') store.me.refreshMemberships() // needed for the invite notifications - if (hasSetup) { - console.log('Updating notifications feed') - notesView?.update() - } else { - store.nav.setTitle(navIdx, 'Notifications') - const newNotesView = new NotificationsViewModel(store, {}) - setNotesView(newNotesView) - newNotesView.setup().then(() => { - if (aborted) return - setHasSetup(true) + store.me.notifications + .update() + .catch(e => { + console.error('Error while updating notifications feed', e) }) - } - return () => { - aborted = true - } + .then(() => { + store.me.notifications.updateReadState() + }) + store.nav.setTitle(navIdx, 'Notifications') }, [visible, store]) const onPressTryAgain = () => { - notesView?.refresh() + store.me.notifications.refresh() } return ( <View style={{flex: 1}}> <ViewHeader title="Notifications" /> - {notesView && <Feed view={notesView} onPressTryAgain={onPressTryAgain} />} + <Feed view={store.me.notifications} onPressTryAgain={onPressTryAgain} /> </View> ) } |