about summary refs log tree commit diff
path: root/src/state/models/invited-users.ts
blob: cd36670622cbe3c0b7bf0273de18c3ef82bfa03c (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
import {makeAutoObservable, runInAction} from 'mobx'
import {ComAtprotoServerDefs, AppBskyActorDefs} from '@atproto/api'
import {RootStoreModel} from './root-store'
import {isObj, hasProp, isStrArray} from 'lib/type-guards'

export class InvitedUsers {
  copiedInvites: string[] = []
  seenDids: string[] = []
  profiles: AppBskyActorDefs.ProfileViewDetailed[] = []

  get numNotifs() {
    return this.profiles.length
  }

  constructor(public rootStore: RootStoreModel) {
    makeAutoObservable(
      this,
      {rootStore: false, serialize: false, hydrate: false},
      {autoBind: true},
    )
  }

  serialize() {
    return {seenDids: this.seenDids, copiedInvites: this.copiedInvites}
  }

  hydrate(v: unknown) {
    if (isObj(v) && hasProp(v, 'seenDids') && isStrArray(v.seenDids)) {
      this.seenDids = v.seenDids
    }
    if (
      isObj(v) &&
      hasProp(v, 'copiedInvites') &&
      isStrArray(v.copiedInvites)
    ) {
      this.copiedInvites = v.copiedInvites
    }
  }

  async fetch(invites: ComAtprotoServerDefs.InviteCode[]) {
    // pull the dids of invited users not marked seen
    const dids = []
    for (const invite of invites) {
      for (const use of invite.uses) {
        if (!this.seenDids.includes(use.usedBy)) {
          dids.push(use.usedBy)
        }
      }
    }

    // fetch their profiles
    this.profiles = []
    if (dids.length) {
      try {
        const res = await this.rootStore.agent.app.bsky.actor.getProfiles({
          actors: dids,
        })
        runInAction(() => {
          // save the ones following -- these are the ones we want to notify the user about
          this.profiles = res.data.profiles.filter(
            profile => !profile.viewer?.following,
          )
        })
        this.rootStore.me.follows.hydrateMany(this.profiles)
      } catch (e) {
        this.rootStore.log.error(
          'Failed to fetch profiles for invited users',
          e,
        )
      }
    }
  }

  isInviteCopied(invite: string) {
    return this.copiedInvites.includes(invite)
  }

  setInviteCopied(invite: string) {
    if (!this.isInviteCopied(invite)) {
      this.copiedInvites.push(invite)
    }
  }

  markSeen(did: string) {
    this.seenDids.push(did)
    this.profiles = this.profiles.filter(profile => profile.did !== did)
  }
}