const e = require("b4a"),
{ ReactionSchema: t } = require("@holepunchto/keet-core-schemas"),
{ AddReactionOperation: i, RemoveReactionOperation: s } = t.Operations,
a = 32,
n = 3,
o = e.alloc(1)
function c(e, t, i) {
const s = e.reactions.findIndex((e) => e.text === i)
if (-1 !== s) {
const i = e.reactions[s]
;((i.count += 1), i.latest.unshift(t), i.latest.length > 3 && i.latest.pop())
} else e.reactions.push({ text: i, count: 1, latest: [t] })
;(e.reactions.length > a && e.reactions.pop(), e.reactions.sort())
}
function r(e, t, i) {
const s = e.reactions.findIndex((e) => e.text === i)
if (-1 === s) return
const a = e.reactions[s]
if (((a.count -= 1), a.count > 0)) {
const e = a.latest.findIndex((e) => l(e, t))
;-1 !== e && a.latest.splice(e, 1)
} else e.reactions.splice(s, 1)
e.reactions.sort()
}
function h() {
return { total: 0, reactions: [] }
}
function l(t, i) {
return e.equals(t, i)
}
module.exports = class {
static Operations = new Set([i.TYPE, s.TYPE])
constructor(e) {
;((this.view = e),
(this.chat = null),
(this.members = null),
(this.reactions = null),
(this.reactionDigests = null),
(this.reactionsByMember = null))
}
initialize() {
;((this.chat = this.view.chat),
(this.members = this.view.members),
(this.reactions = this.view.collections.reactions),
(this.reactionDigests = this.view.indexes.reactionDigests),
(this.reactionsByMember = this.view.indexes.reactionsByMember))
}
async _applyAddReactionOperation(e, { id: t }) {
const { to: i, text: s } = e.value,
[a, n, c] = await Promise.all([
this.members.getMemberForDeviceKey(t.key),
this.chat.getEventId(i),
this.members.isDeviceMuted(t.key),
])
!c && a && n && (await this.reactions.update([...n, a.key, s], o, { upsert: !0 }))
}
async _applyRemoveReactionOperation(e, { id: t }) {
const { to: i, text: s } = e.value,
[a, n, o] = await Promise.all([
this.members.getMemberForDeviceKey(t.key),
this.chat.getEventId(i),
this.members.isDeviceMuted(t.key),
])
o ||
(a &&
n &&
a &&
n &&
(await this.reactions.get([...n, a.key, s])) &&
(await this.reactions.delete([...n, a.key, s])))
}
async _indexReactionDigests(e, t, i) {
const [s, a, n, o] = i,
l = [s, a, n],
u = [s, a],
m = await this.reactionsByMember.get(l),
d = m?.value,
p = await this.reactionDigests.get(u),
y = p ? p.value : h()
;(e && t) ||
(e && (r(y, n, o), d && d.length <= 1 && (y.total -= 1)),
t && (c(y, n, o), d || (y.total += 1)),
y.total > 0 ? await this.reactionDigests.insert(u, y) : await this.reactionDigests.delete(u))
}
async _indexReactionsByMember(e, t, i) {
const [s, a, n, o] = i,
c = [s, a, n],
r = await this.reactionsByMember.get(c),
h = r?.value
if (e && h) {
const e = h.indexOf(o)
;-1 !== e &&
(h.splice(e, 1),
h.length > 0
? await this.reactionsByMember.insert(c, h)
: await this.reactionsByMember.delete(c))
}
t &&
(h
? -1 === h.indexOf(o) && (h.push(o), h.sort(), await this.reactionsByMember.insert(c, h))
: await this.reactionsByMember.insert(c, [o]))
}
autobaseApply(e, t) {
switch (e.type) {
case i.TYPE:
return this._applyAddReactionOperation(e, t)
case s.TYPE:
return this._applyRemoveReactionOperation(e, t)
}
}
async autobaseIndex({ prev: e, next: t, id: i }) {
;(await this._indexReactionDigests(e, t, i), await this._indexReactionsByMember(e, t, i))
}
}