Spaces:
Sleeping
Sleeping
| const EMPTY_BOARD = { to_me: [], by_me: [], together: [], hidden: [], no_go: [] }; | |
| export function sortedBoardItems(items) { | |
| return [...items].sort( | |
| (left, right) => (right.popularity || 0) - (left.popularity || 0) || left.name.localeCompare(right.name), | |
| ); | |
| } | |
| export function optimisticBoard(previousBoard, kinkId, interestState, directions, qc, auth) { | |
| const kid = String(kinkId); | |
| const nextBoard = Object.fromEntries( | |
| Object.entries(previousBoard || EMPTY_BOARD).map(([key, items]) => [ | |
| key, | |
| (items || []).filter((item) => String(item.id) !== kid), | |
| ]), | |
| ); | |
| const sourceItem = | |
| findBoardItemInData(previousBoard, kid) || (qc ? findBoardItemFromQuery(qc, auth, kid) : null); | |
| /** If play-board has not loaded yet (or kink not in recs cache), still place a stub so we never strip a row and return empty buckets. */ | |
| const itemBase = sourceItem || { id: kid, name: kid, summary: "", popularity: 0 }; | |
| const item = { ...itemBase, interest_state: interestState, directions }; | |
| if (interestState === "hard_no") { | |
| nextBoard.no_go.push(item); | |
| } else if (interestState === "not_interested") { | |
| nextBoard.hidden.push(item); | |
| } else { | |
| const targetDirections = directions.length ? directions : ["together"]; | |
| for (const direction of targetDirections) { | |
| if (nextBoard[direction]) nextBoard[direction].push({ ...item }); | |
| } | |
| } | |
| for (const key of Object.keys(nextBoard)) nextBoard[key] = sortedBoardItems(nextBoard[key]); | |
| return nextBoard; | |
| } | |
| export function findBoardItemInData(board, kinkId) { | |
| const kid = String(kinkId); | |
| for (const items of Object.values(board || EMPTY_BOARD)) { | |
| const match = (items || []).find((item) => String(item.id) === kid); | |
| if (match) return match; | |
| } | |
| return null; | |
| } | |
| function normalizeKinkItem(raw) { | |
| if (!raw?.id || !raw?.name) return null; | |
| return { | |
| id: raw.id, | |
| name: raw.name, | |
| summary: raw.summary || raw.definition || raw.detail_summary || "", | |
| popularity: raw.popularity || 0, | |
| }; | |
| } | |
| function findInItemsPayload(payload, kinkId) { | |
| const kid = String(kinkId); | |
| const match = payload?.items?.find((item) => String(item?.kink?.id) === kid); | |
| return normalizeKinkItem(match?.kink || null); | |
| } | |
| function findBoardItemFromQuery(qc, auth, kinkId) { | |
| const detail = qc.getQueryData(["kink", kinkId]); | |
| const fromDetail = normalizeKinkItem(detail); | |
| if (fromDetail) return fromDetail; | |
| const scopedKeys = [ | |
| ["recs", auth?.userId, ""], | |
| ["prompts", auth?.userId, ""], | |
| ]; | |
| for (const key of scopedKeys) { | |
| const fromScoped = findInItemsPayload(qc.getQueryData(key), kinkId); | |
| if (fromScoped) return fromScoped; | |
| } | |
| const queryCache = qc.getQueryCache(); | |
| const itemQueries = queryCache.findAll({ predicate: (query) => { | |
| const key = query.queryKey || []; | |
| return key[0] === "recs" || key[0] === "prompts" || key[0] === "search"; | |
| }}); | |
| for (const query of itemQueries) { | |
| const fromItems = findInItemsPayload(query.state?.data, kinkId); | |
| if (fromItems) return fromItems; | |
| } | |
| const overlapQueries = queryCache.findAll({ predicate: (query) => (query.queryKey || [])[0] === "group-overlap" }); | |
| for (const query of overlapQueries) { | |
| const data = query.state?.data || {}; | |
| const direct = (data.direct_matches || []).find((item) => item?.id === kinkId); | |
| if (direct) return normalizeKinkItem(direct); | |
| const similar = (data.similar_matches || []).find((item) => item?.kink?.id === kinkId)?.kink; | |
| const fromSimilar = normalizeKinkItem(similar); | |
| if (fromSimilar) return fromSimilar; | |
| } | |
| return null; | |
| } | |
| export function removeKinkFromItemsPayload(payload, kinkId) { | |
| if (!payload?.items) return payload; | |
| const kid = String(kinkId); | |
| return { | |
| ...payload, | |
| items: payload.items.filter((item) => String(item?.kink?.id) !== kid), | |
| }; | |
| } | |
| export function playCommitKey(kinkId, interestState, directions = []) { | |
| return `${kinkId}::${interestState}::${[...(directions || [])].sort().join("|")}`; | |
| } | |