import { getChatMessagesApiPromise as t } from "../../../api/core"
import { first as e, last as o } from "../../lib/array"
import { MESSAGE_CATEGORY as r } from "../chat.constant"
import { calcMessageCategory as a } from "../message"
import { PORTION_SIZE_MAX as n, PORTION_SIZE_MIN as s, EMPTY_ARRAY as c } from "./loader.constants"
export const createCtrlCtxRef = () => {
let t = 0,
e = () => {}
return {
callCount: 0,
queries: [],
waitStart: async () =>
t ||
(await new Promise((t) => {
e = t
}),
t),
startQuery() {
t || ((t = Date.now()), e())
},
doneQuery(t) {
;((this.callCount += 1), (this.queries[this.callCount] = t))
},
}
}
const l = (t, e) => {
const { length: o } = t,
n = { ...e }
for (let e = 0; e < o; e += 1) {
const o = t[e],
s = a(o)
;(s === r.NO_CATEGORY
? n.lastCategory === r.NO_CATEGORY
? (n.count += 1)
: (n.count += 2)
: n.lastCategory !== s && n.lastCategory !== r.NO_CATEGORY && (n.count += 1),
(n.lastCategory = s))
}
return n
}
export const loadMsgsBefore = async ({
roomId: e,
topSeq: o,
topMsgCategory: r,
expectedCount: a,
ctxRef: c,
}) => {
let u,
g,
C = Math.max(a, s),
i = { count: 0, lastCategory: r },
m = o
do {
if (((g = m - 1), g < 0)) break
;((m = Math.max(g - (C - 1), 0)), c?.startQuery())
const o = await t(e, { reverse: !0, gte: m, lte: g })
;(c?.doneQuery({ gte: m, lte: g }),
(i = l(o, i)),
(u = u ? u.concat(o) : o),
(C = Math.min(C + C, n)))
} while (i.count < a)
return u
}
const u = (t, e) => {
const { length: o } = t,
n = { ...e }
for (let e = o - 1; e >= 0; e -= 1) {
const o = t[e],
s = a(o)
;(s === r.NO_CATEGORY
? n.lastCategory === r.NO_CATEGORY
? (n.count += 1)
: (n.count += 2)
: n.lastCategory !== s && n.lastCategory !== r.NO_CATEGORY && (n.count += 1),
(n.lastCategory = s))
}
return n
}
export const loadMsgsAfter = async ({
roomId: e,
bottomSeq: o,
bottomMsgCategory: r,
expectedCount: a,
count: c,
ctxRef: l,
}) => {
let g,
C = Math.max(a, s)
const i = c - 1
let m,
y = { count: 0, lastCategory: r },
f = o
do {
if (((m = f + 1), m > i)) break
;((f = Math.min(m + (C - 1), i)), l?.startQuery())
const o = await t(e, { reverse: !0, gte: m, lte: f })
;(l?.doneQuery({ lte: f, gte: m }),
(y = u(o, y)),
(g = g ? o.concat(g) : o),
(C = Math.min(C + C, n)))
} while (y.count < a)
return g
}
const g = (t) => {
const { length: e } = t
let o = 0,
n = r.NO_CATEGORY
for (let s = 0; s < e; s += 1) {
const e = t[s],
c = a(e)
;((c !== r.NO_CATEGORY && n === c) || (o += 1), (n = c))
}
return o
}
export const loadInitial = async ({ roomId: n, gte: s, lte: l, count: u, ctxRef: C }) => {
C?.startQuery()
let i = await t(n, { reverse: !0, gte: s, lte: l })
if ((C?.doneQuery({ gte: s, lte: l }), !i.length)) return c
const m = l - s + 1,
y = g(i),
f = o(i),
d = a(f),
O = e(i),
p = a(O)
if (p !== r.NO_CATEGORY || y < m) {
const t = await loadMsgsAfter({
roomId: n,
bottomSeq: O.seq,
bottomMsgCategory: p,
expectedCount: 1,
count: u,
ctxRef: C,
})
i = t ? t.concat(i) : i
}
if (d !== r.NO_CATEGORY) {
const t = Math.max(m - y, 1),
e = await loadMsgsBefore({
roomId: n,
topSeq: f.seq,
topMsgCategory: d,
expectedCount: t,
ctxRef: C,
})
i = e ? i.concat(e) : i
}
return i
}