about summary refs log tree commit diff
path: root/src/state/models/me.ts
blob: 201ce04c72575c8e0a4460afe6cd327b83967b04 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import {makeAutoObservable, runInAction} from 'mobx'
import {RootStoreModel} from './root-store'
import {FeedModel} from './feed-view'
import {NotificationsViewModel} from './notifications-view'
import {isObj, hasProp} from '../lib/type-guards'

export class MeModel {
  did: string = ''
  handle: string = ''
  displayName: string = ''
  description: string = ''
  avatar: string = ''
  notificationCount: number = 0
  mainFeed: FeedModel
  notifications: NotificationsViewModel

  constructor(public rootStore: RootStoreModel) {
    makeAutoObservable(
      this,
      {rootStore: false, serialize: false, hydrate: false},
      {autoBind: true},
    )
    this.mainFeed = new FeedModel(this.rootStore, 'home', {
      algorithm: 'reverse-chronological',
    })
    this.notifications = new NotificationsViewModel(this.rootStore, {})
  }

  clear() {
    this.did = ''
    this.handle = ''
    this.displayName = ''
    this.description = ''
    this.avatar = ''
    this.notificationCount = 0
  }

  serialize(): unknown {
    return {
      did: this.did,
      handle: this.handle,
      displayName: this.displayName,
      description: this.description,
      avatar: this.avatar,
    }
  }

  hydrate(v: unknown) {
    if (isObj(v)) {
      let did, handle, displayName, description, avatar
      if (hasProp(v, 'did') && typeof v.did === 'string') {
        did = v.did
      }
      if (hasProp(v, 'handle') && typeof v.handle === 'string') {
        handle = v.handle
      }
      if (hasProp(v, 'displayName') && typeof v.displayName === 'string') {
        displayName = v.displayName
      }
      if (hasProp(v, 'description') && typeof v.description === 'string') {
        description = v.description
      }
      if (hasProp(v, 'avatar') && typeof v.avatar === 'string') {
        avatar = v.avatar
      }
      if (did && handle) {
        this.did = did
        this.handle = handle
        this.displayName = displayName || ''
        this.description = description || ''
        this.avatar = avatar || ''
      }
    }
  }

  async load() {
    const sess = this.rootStore.session
    if (sess.hasSession && sess.data) {
      this.did = sess.data.did || ''
      this.handle = sess.data.handle
      const profile = await this.rootStore.api.app.bsky.actor.getProfile({
        actor: this.did,
      })
      runInAction(() => {
        if (profile?.data) {
          this.displayName = profile.data.displayName || ''
          this.description = profile.data.description || ''
          this.avatar = profile.data.avatar || ''
        } else {
          this.displayName = ''
          this.description = ''
          this.avatar = ''
        }
      })
      this.mainFeed = new FeedModel(this.rootStore, 'home', {
        algorithm: 'reverse-chronological',
      })
      this.notifications = new NotificationsViewModel(this.rootStore, {})
      await Promise.all([
        this.mainFeed.setup().catch(e => {
          this.rootStore.log.error('Failed to setup main feed model', e)
        }),
        this.notifications.setup().catch(e => {
          this.rootStore.log.error('Failed to setup notifications model', e)
        }),
      ])
    } else {
      this.clear()
    }
  }

  clearNotificationCount() {
    this.notificationCount = 0
  }

  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()
      }
    })
  }
}