import { FEATURES as o } from "@holepunchto/keet-core/features"
import { buffers as e, channel as t } from "redux-saga"
import {
fork as i,
select as r,
call as a,
put as d,
takeEvery as n,
takeLatest as l,
take as c,
delay as s,
flush as y,
race as m,
takeLeading as p,
} from "redux-saga/effects"
import { getCoreBackend as f } from "../../../backend"
import { apiCall as u, searchRoomsApi as g } from "../../../api/core"
import { taskErrorSaga as R } from "../../error"
import { apiSubscribeSaga as h, forkChildren as I, apiSubscribeLatest as b } from "../../lib"
import { normalizedIncludes as L } from "../../lib/string"
import { identityFeatureGate as S, setBlockedMembers as E } from "../../identity"
import {
getChatLastMessageByRoomId as A,
setChatMessageLastSeen as v,
updateChatLastMessage as D,
updateChatLastMessageBlocked as O,
sendChatMessageSuccess as U,
chatSubscribeUnreadSaga as F,
chatUnreadSyncData as k,
} from "../../chat"
import {
getRoomListSearchText as V,
searchAllRooms as M,
getRoomListAllIds as x,
setSearchRoomIds as N,
getRoomListInViewIds as C,
getRoomListInViewOverscanIds as T,
setItemsInView as _,
roomListInViewIdsChangeEvt as w,
setRoomListSearchError as B,
setUnreadRoomsCount as P,
getRoomListUnreadRoomsCount as j,
getRoomListSearchIds as G,
setRoomListIsSearching as H,
getRoomListIsSearching as W,
getRecentRoomsBufferInterval as K,
setScrollToRoomId as q,
setRoomFilterMap as z,
getRoomFilterMap as J,
} from "./room-list.reducer"
import {
setAllRooms as Q,
updateRecentRooms as X,
addOrRemoveRecentRoom as Y,
createRoomSubmit as Z,
setFavoriteRooms as $,
toggleRoomFavoriteCmd as oo,
addOrRemoveFavoriteRoom as eo,
toggleRoomIsUnreadCmd as to,
} from "../room.action"
import {
getRoomAllNotifications as io,
getRoomIsUnread as ro,
getRoomItemById as ao,
getRoomNotificationById as no,
getRoomState as lo,
} from "../room.selector"
import {
RECENT_ROOM_UPDATE as co,
ROOM_PREFERENCES as so,
defaultRoomPreferences as yo,
} from "../room.constant"
import {
parseRecentRoomsAllResponse as mo,
parseRecentRoomsChangeResponse as po,
parseRecentRoomsAddRemoveResponse as fo,
} from "../room.model"
import {
getPreferencesNotificationsType as uo,
getPreferencesRoomListFilter as go,
NOTIFICATIONS_TYPES as Ro,
PREFERENCES as ho,
updatePreferencesCmd as Io,
} from "../../preferences"
import { roomListItemUpdateSaga as bo } from "./room-list-item-update-saga"
import { setAppCurrentRoomId as Lo, getAppCurrentRoomId as So } from "../../app/app.reducer"
function* Eo({ roomId: o, appVersion: e }) {
try {
const t = f(),
i = yield u(t.getRoomInfo, o),
a = yield r(ao(o))
if (a?.isLoaded) return
yield bo({
data: i,
roomId: o,
appVersion: e,
trackLastMsgUpdates: !1,
trackNotificationsUpdates: !1,
})
} catch (o) {
yield R("preloadRoomListItemSaga", o, { logOnly: !0 })
}
}
function* Ao({ appVersion: o }) {
const e = {},
t = new Map()
yield l([N, Q, X, Y, _, z, $, eo], function* () {
const a = yield r(C)
let n = !1
;(Object.keys(e).forEach((o) => {
a.includes(o) || (delete e[o], (n = !0))
}),
a
.filter((o) => !e[o])
.forEach((o) => {
;((e[o] = !0), (n = !0))
}),
n && (yield d(w(Object.keys(e)))))
const l = yield r(T),
{ roomById: c } = yield r(lo)
for (const e of l) {
if (c[e]?.isLoaded) continue
const r = t.get(e)
if (r?.isRunning()) continue
const a = yield i(Eo, { roomId: e, appVersion: o })
t.set(e, a)
}
})
}
export function* roomSearchSaga() {
const o = yield r(V)
if (o)
try {
;(yield r(W)) || (yield d(H(!0)))
const e = (yield* g()).reduce((e, t) => {
const { title: i, roomId: r } = t
return (i && L(i, o) && e.push(r), e)
}, [])
yield d(N(e))
} catch (o) {
;(yield d(B(o.message)), yield R("roomSearchAll", o, { logOnly: !0 }))
}
else (yield r(G)).length > 0 && (yield d(N([])))
}
export function* roomListDataSaga({ appVersion: o }) {
;(yield n(E, function* ({ payload: { blockedByMemberId: o } }) {
yield d(O({ blockedByMemberId: o }))
}),
yield I(
w,
({ payload: o }) => o,
function* ({ taskId: e }) {
;(yield i(F, { roomId: e }),
yield b(
[f().subscribeRoomInfo, e],
function* (t) {
yield bo({
data: t,
roomId: e,
appVersion: o,
trackLastMsgUpdates: !0,
trackNotificationsUpdates: !0,
})
},
{ onError: (o) => R("roomListItemTask", o) },
))
},
(o) => R("roomListItem", o),
))
}
export function* calculateAndUpdateUnreadRoomsCount() {
try {
const o = yield r(A),
e = yield r(x),
t = yield r(uo),
i = yield r(j),
a = t !== Ro.NONE
let n = 0
if (a) {
const t = yield r(io)
for (const i of e) {
if (!(yield r(no(i)))) continue
const e = t[i] || yo,
a = o[i]
a?.unread && e[so.NOTIFICATIONS] && (n += 1)
}
}
if (i === n) return
yield d(P(n))
} catch (o) {
yield R("calculateAndUpdateUnreadRoomsCount", o)
}
}
export function* throttleRecentRoomChanged(o) {
try {
const e = yield r(K)
for (;;) {
const t = yield c(o),
i = yield y(o)
let r = [t]
;(Array.isArray(i) && (r = i.reverse().concat(t)), yield d(X(r)), yield s(e))
}
} catch (o) {
yield R("throttleRecentRoomUpdates", o)
}
}
const vo = 400
function* Do() {
for (;;) {
yield c(Z)
const { response: o } = yield m({ delay: s(vo), response: c(Y) }),
e = o?.payload
e?.roomId && e.type === co.ADDED && (yield d(q(e.roomId)))
}
}
function* Oo() {
;(yield i(Do),
yield l(U, function* ({ payload: o }) {
yield d(q(o.roomId))
}))
}
export function* toggleRoomFavoriteSaga({ payload: o }) {
try {
const { roomId: e, value: t } = o,
i = f()
yield u(i.setRoomFavorite, e, t)
} catch (o) {
yield R("toggleRoomFavoriteSaga", o)
}
}
function* Uo({ payload: o }) {
try {
const e = yield r(ro(o)),
t = f()
yield u(t.setRoomUnread, o, !e)
} catch (o) {
yield R("toggleRoomIsUnreadSaga", o)
}
}
function* Fo() {
;(yield p(to, Uo),
yield n([Lo, U], function* () {
const o = yield r(So)
;(yield r(ro(o))) && (yield Uo({ payload: o }))
}))
}
function* ko() {
try {
yield h(
[f().subscribeFavoriteRooms, {}],
function* (o) {
switch (o.type) {
case co.ALL:
return void (yield d($(mo(o))))
case co.CHANGED:
return
case co.ADDED:
case co.REMOVED:
return void (yield d(eo(fo(o))))
default:
yield R("subscribeRecentRooms", "invalid data", { logWarn: !0 })
}
},
{ onError: (o) => R("subscribeFavoriteRooms", o) },
)
} catch (o) {
yield R("roomListFavoritesSub", o)
}
}
export function* roomListFilterPreferencesSaga() {
try {
const o = yield r(go)
;(yield d(z(o)),
yield l(z, function* () {
const o = yield r(J)
yield d(Io(ho.ROOM_LIST_FILTER, o))
}))
} catch (o) {
yield R("roomListFilterPreferencesSaga", o)
}
}
export function* roomListSaga({ appVersion: r }) {
try {
;(yield l([M, Y], roomSearchSaga),
yield n([D, v, k], calculateAndUpdateUnreadRoomsCount),
yield i(roomListFilterPreferencesSaga),
yield i(Ao, { appVersion: r }),
yield i(S(o.FAVORITE_ROOMS, ko)),
yield l(oo, toggleRoomFavoriteSaga),
yield i(S(o.ROOM_MARK_UNREAD, Fo)),
yield i(roomListDataSaga, { appVersion: r }),
yield i(Oo))
const c = yield a(t, e.expanding(20))
;(yield i(throttleRecentRoomChanged, c),
yield h(
[f().subscribeRecentRooms, {}],
function* (o) {
switch (o.type) {
case co.ALL:
return void (yield d(Q(mo(o))))
case co.CHANGED:
return void (yield d(c, po(o)))
case co.ADDED:
case co.REMOVED:
return void (yield d(Y(fo(o))))
default:
yield R("subscribeRecentRooms", "invalid data", { logWarn: !0 })
}
},
{ onError: (o) => R("subscribeRecentRooms", o) },
))
} catch (o) {
yield R("roomListSaga", o)
}
}