OverviewFilesCommitsIssuesDocsReleasesPeers

keet-deobfuscated / @holepunchto / keet-store / store / chat / list-view / list-view.saga.js

195 lines · javascript ref:
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)
}