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