OverviewFilesCommitsIssuesDocsReleasesPeers

keet-cli / keet-core-4.14.4-pretty / lib / core / sync / index.js

195 lines · javascript ref:
const e = require("hypercore-id-encoding"),
  t = require("ready-resource"),
  s = require("./updater"),
  { roomsStats: a } = require("../contract/stats/local")
module.exports = class extends t {
  constructor(e, t, s, a) {
    ;(super(),
      (this.keet = e),
      (this.view = t),
      (this.base = s),
      (this.changes = a),
      (this._events = []),
      (this._swappedId = !1),
      (this._updater = null))
  }
  async _close() {
    this._updater && (await this._updater.close())
  }
  async _save() {
    const t = await this.keet.internalEnterLocalTransaction()
    try {
      const s = this._updater.updates.startIdentitySwap,
        i = this._updater.updates.finishIdentitySwap
      if (s) {
        const e = this._updater.currentIdentityInfo
        ;((e.swapV2 = s), await t.insert("@local/identity", e))
      }
      if (
        (i && (await t.insert("@local/identity", i), (this._swappedId = !0)),
        this._updater.updates.contacts)
      )
        for (const e of this._updater.updates.contacts) await t.insert("@local/contacts", e)
      if (this._updater.updates.sharedPreferences)
        for (const s of this._updater.updates.sharedPreferences) {
          const a = await t.get("@local/room-preferences", s)
          await t.insert("@local/room-preferences", s)
          const i = await t.get("@local/rooms", s)
          ;(i && ((i.preferences = s.status), await t.insert("@local/rooms", i)),
            s.status.isActive &&
              this._events.push({
                type: "recent-rooms-changed",
                args: ["changed", 0, e.encode(s.roomKey)],
              }))
          const r = !1 === a?.status.isFavorite && s.status.isFavorite,
            o = !0 === a?.status.isFavorite && !s.status.isFavorite
          r || o
            ? this._events.push({
                type: "favorite-rooms-changed",
                args: [o ? "removed" : "added", 0, e.encode(s.roomKey)],
              })
            : s.status.isFavorite &&
              s.status.isActive &&
              this._events.push({
                type: "favorite-rooms-changed",
                args: ["changed", 0, e.encode(s.roomKey)],
              })
        }
      if (this._updater.updates.cache) {
        const e = this._updater.updates.cache
        ;(e.device &&
          (await t.insert("@local/devices", { roomKey: this.base.key, device: e.device })),
          e.member && (await t.insert("@local/members", e.member)))
      }
      const r = await t.get("@local/rooms", this._updater.roomInfo)
      if (!r) {
        const e = await t.get("@local/room-preferences", this._updater.roomInfo)
        e && (this._updater.roomInfo.preferences = e.status)
      }
      ;(await t.insert("@local/rooms", this._updater.roomInfo),
        await a(t, this._updater.roomInfo, r),
        await t.flush())
    } finally {
      await this.keet.internalExitLocalTransaction()
    }
  }
  async _dispatch() {
    const e = this._updater.updates.dispatches
    if (e && 0 !== e.length)
      try {
        await this.keet.dispatchBatch(this.base.id, e)
      } catch (e) {
        this.keet.onerror(e)
      }
  }
  async _profileDispatch() {
    if (!this._updater.currentIdentityInfo) return
    const t = this._updater.updates.profileDispatches
    if (t && 0 !== t.length)
      try {
        const s = e.encode(this._updater.currentIdentityInfo.privateProfileKey)
        await this.keet.dispatchBatch(s, t)
      } catch (e) {
        this.keet.onerror(e)
      }
  }
  _generateEvents() {
    this._events.push({ type: "room-changed", args: [this.base.id] })
    const { roomKey: t, discoveryKey: s, timestamps: a } = this._updater.roomInfo,
      i = a.latestChatMessage || a.latestSync,
      r = this._updater.roomInfo && !this._updater.currentRoomInfo,
      o =
        !this._updater.roomInfo.status.isRemoved && this._updater.currentRoomInfo?.status.isRemoved,
      n =
        this._updater.roomInfo.status.isRemoved && !this._updater.currentRoomInfo?.status.isRemoved,
      h = this._updater.roomInfo.status.isRemoved,
      d = !!this._updater.roomInfo.dm,
      c = !(h || n || r || o)
    if (
      ((r || o || n) &&
        (this._events.push({
          type: "recent-rooms-changed",
          args: [n ? "removed" : "added", i, this.base.id],
        }),
        this._updater.roomInfo.preferences?.isFavorite &&
          this._events.push({
            type: "favorite-rooms-changed",
            args: [n ? "removed" : "added", i, this.base.id],
          }),
        (r || o) && this._events.push({ type: "room-preferences-changed", args: ["join", t, s] }),
        n && this._events.push({ type: "room-preferences-changed", args: ["leave", t, s] }),
        r && d && this._events.push({ type: "dm-rooms-changed", args: [] })),
      this._updater.updates.chat &&
        (c &&
          (this._events.push({ type: "recent-rooms-changed", args: ["changed", i, this.base.id] }),
          this._updater.roomInfo.preferences?.isFavorite &&
            this._events.push({
              type: "favorite-rooms-changed",
              args: ["changed", i, this.base.id],
            })),
        h ||
          this._events.push({
            type: "chat-changed",
            args: [this.base.id, this._updater.updates.chat.id.index],
          })),
      this._updater.isCurrentPrivateProfile &&
        this._events.push({ type: "identity-changed", args: [] }),
      this._updater.updates.sharedPreferences)
    )
      for (const { roomKey: t, status: s } of this._updater.updates.sharedPreferences)
        (s.isFullyMuted &&
          this._events.push({ type: "room-preferences-changed", args: ["mute", t] }),
          s.isFullyMuted ||
            this._events.push({ type: "room-preferences-changed", args: ["unmute", t] }),
          this._events.push({ type: "room-changed", args: [e.encode(t)] }))
    if (this._updater.updates.activeCallSynced) {
      const e = this._updater.updates.activeCall,
        t = this._updater.updates.activeCallDevice
      this._events.push({ type: "call-changed", args: [this.base.id, e, t] })
    }
  }
  async _runPostUpdate() {
    try {
      if ((await this.base.update(), this.keet.closing)) return
      if ((await this._dispatch(), this.keet.closing)) return
      if ((await this._profileDispatch(), this.keet.closing)) return
      if (this._updater.updates.shouldUpgrade) {
        const t = e.encode(this._updater.roomInfo.roomKey)
        await this.keet.internalDispatchUpgrade(t, this.keet.abi.autoupgrade)
      }
      if (this._updater.updates.tasks)
        for (const e of this._updater.updates.tasks) e.runBackground()
      for (const { type: e, args: t } of this._events) this.keet.emit(e, ...t)
      ;(this._updater.changes.logout && (await this.keet.logout()),
        this._updater.updates.unreadKeys && (await this.keet.internalRefreshUnreads()))
      for (const { type: e, value: t } of this._updater.events) {
        const s = {
          roomKey: this.base.key,
          roomId: this.base.id,
          roomInfo: this._updater.roomInfo,
          value: t,
        }
        this.keet.emit(e, s)
      }
    } catch (e) {
      this.keet.onerror(e)
    }
  }
  async run() {
    try {
      if (
        ((this._updater = new s(this.keet, this.view, this.base, this.changes)),
        !(await this._updater.run()) || this.closing)
      )
        return
      if ((await this._save(), this.closing)) return
      ;(this._swappedId && this.keet.internalSafeSwapPrivateProfiles(), this._generateEvents())
    } finally {
      await this.close()
    }
  }
  runPostUpdate() {
    queueMicrotask(this._runPostUpdate.bind(this))
  }
}