import {
put as t,
fork as e,
select as i,
take as o,
takeEvery as n,
delay as l,
takeLatest as s,
race as r,
} from "redux-saga/effects"
import { getCoreBackend as a } from "../../../backend"
import { apiCall as d } from "../../../api/core"
import { taskErrorSaga as c, logWarning as y } from "../../error"
import {
setChatMessageCount as m,
createFirstQuery as u,
createFetchQuery as f,
createFirstMiddleQuery as h,
} from "../message"
import { isUnsetRange as g, isSeqInRange as p } from "../chat.model"
import { VIEW_MODE as L, ANCHOR_STATUS as R } from "./list-view.constant"
import {
getChatState as w,
getChatMessageState as E,
getChatMessageSeqLoaded as I,
} from "./list-view-data.selector"
import {
getChatMessageAnchor as S,
getChatMessagesInView as C,
getChatMessageStartSeq as v,
getChatListViewConfig as O,
getChatListViewLive as b,
getChatListViewStopAnchor as T,
getChatListViewState as V,
getChatLastSeenMessageSeq as A,
} from "./list-view.selector"
import { fetchMessagesCmd as H, reloadMessagesCmd as $ } from "./list-view-data.action"
import {
setChatListViewMode as D,
setChatMessagesInView as k,
setChatMessageAnchor as N,
incChatListAnchorRetryCount as _,
setChatListViewStopAnchor as x,
chatListViewOnScroll as q,
setChatListViewStartSeenSeq as M,
} from "./list-view.action"
import { isAnchorScrollProcessed as Y, shouldStartHistory as F } from "./list-view.model"
import { CHAT_WORKER as G } from "../chat.constant"
import { sharedCoreMessagesUpdate as U } from "../../api/data.action"
export function* chatListViewChangeHandler() {
const { count: e } = yield i(E),
{ inView: o, anchor: n } = yield i(V)
if (g(o)) return
if (n && n.status !== R.RENDERED) return
const { top: l, bottom: s } = o,
r = f({ gte: l, lte: s }, e)
yield t(H(r))
}
export function* chatListViewCountChangeHandler({ length: e, reordered: o }) {
const {
listView: { mode: n, inView: l },
message: { count: s, seqLoaded: r },
} = yield i(w)
if (e < s) {
if (!e) {
const t = `Zero messages count: prev=${s} next=${e} reordered=${o} mode=${n}`
return void (yield c("chatListViewCountChangeHandler", t))
}
const l = `Incorrect messages count: prev=${s} next=${e} reordered=${o}`
;(yield c("chatListViewCountChangeHandler", l, { logWarn: !0 }), yield t(m(e)))
const {
listView: { inView: r },
message: { count: a },
} = yield i(w),
d = f({ gte: r.top, lte: r.bottom }, a)
return void (yield t($(d)))
}
if (s !== e) {
yield t(m(e))
const { anchor: o } = yield i(V),
{ top: s, bottom: a } = l
if (n === L.FRESH_LOADING) {
const i = f({ gte: s, lte: a }, e)
yield t(H(i))
}
if (n === L.LATEST) {
const i =
o?.lastMessage && o.status !== R.RENDERED ? u({ count: e }) : f({ gte: s, lte: a }, e)
yield t(H(i))
}
if (n === L.ON_HOLD) {
const o = yield i(A)
yield t(M(o))
const n = f({ gte: s, lte: a }, e)
;(yield t(H(n)), yield t(D(L.HISTORY)))
}
n === L.HISTORY &&
a === r.bottom &&
(yield c("chatListViewCountChangeHandler", `incorrect bottom=${a} load`, { logWarn: !0 }))
} else if (n === L.FRESH_LOADING) {
const { top: e, bottom: i } = l,
o = f({ gte: e, lte: i }, s)
yield t(H(o))
}
o && (yield t($()))
}
export function* chatListViewClearAnchorSaga() {
const s = yield i(S),
{
ANCHOR_CLEAR_TIMEOUT: a,
ANCHOR_DISMISS_TIMEOUT: d,
ANCHOR_SCROLL_RETRY_COUNT: c,
} = yield i(O)
let m,
u = { id: "", task: null }
function* f(e) {
let n = e,
s = n
const u = n.startTime
do {
if (n.status === R.RENDERED) return (yield l(a), void (yield t(N(null))))
if (n.retryCountProcessed >= c && n.status !== R.RETRY && !n.lastMessage)
return void (yield t(N(null)))
if (
(Y(n.status) && m[0] && (yield t(_())),
Date.now() - u >= (n.retryCountProcessed + 1) * d && s?.status !== R.ASKED)
) {
const e = yield i(I),
o = yield i(C)
return (
yield t(
y({
message: "chat anchor dismissed on timeout",
stack: `clearAnchor: ${n.seq}: seqLoaded={top: ${e.top}, bottom:${e.bottom}} inView={top:${o.top}, bottom:${o.bottom}}`,
}),
),
void (yield t(N(null)))
)
}
;((s = n), (m = yield r([o(k), l(d)])), (n = yield i(S)))
} while (n)
}
;(s && (u = { id: s.messageId, task: yield e(f, s) }),
yield n([U, N], function* () {
const t = yield i(S)
;(u.task && ((t && u.id === t.messageId) || (u.task.cancel(), (u = { id: "", task: null }))),
t && !u.task && (u = { id: t.messageId, task: yield e(f, t) }))
}))
}
export function* chatListInitialLoad({ roomId: e, coreEventChannel: o }) {
try {
yield t(D(L.RESTORE_LAST))
const n = yield d(a().getChatLength, e),
{ length: l } = n
if ((yield t(m(l)), 0 === l)) return !1
const s = yield i(v),
r = F({ count: l, startSeq: s }) ? h({ count: l, bottomSeq: s }) : u({ count: l }),
c = a(),
y = yield d(c.getChatMessages, e, { reverse: !0, ...r })
yield t(o, { worker: G.INITIAL, events: y })
} catch (t) {
yield c("chatListInitialLoad", t)
}
return !0
}
export function* chatListInitialRender() {
try {
let e = !1
const n = yield i(v)
for (
n < 0 &&
(yield t(y({ message: `chat: invalid startSeq=${n}`, stack: "chatListInitialRender" })));
;
) {
const l = yield i(C),
s = yield i(T)
if ((g(l) || (e = -1 === n || p(l, n) || s), e)) {
const e = yield i(I)
s && l.bottom === e.bottom && (yield t(x(!1)))
break
}
yield o(k)
}
yield t(D(L.FRESH_LOADING))
} catch (t) {
yield c("chatListInitialRender", t)
}
}
export function* chatListViewOnScrollSaga() {
;(yield i(b)) ? (yield i(S)) && (yield t(N(null))) : yield t(x(!0))
}
export function* chatListViewAnchorSaga() {
yield s(q, chatListViewOnScrollSaga)
}