OverviewFilesCommitsIssuesDocsReleasesPeers

keet-deobfuscated / @holepunchto / keet-store / store / media / file / file.reducer.js

354 lines · javascript ref:
import { createSelector as e } from "@reduxjs/toolkit"
import { EMPTY_ARRAY as t } from "../../lib/array"
import {
  getCanPreviewFile as o,
  getFileId as l,
  getHttpLinkPreview as d,
  isFileEntryChanged as s,
  mergeFileEntry as i,
  PREVIEW_SIZE as a,
} from "./file.model"
import { CLEAR_ALL_STATUS as r } from "./file.constants"
import { sharedCoreMessagesUpdate as n } from "../../api/data.action"
import {
  removeFileEntries as y,
  addAvatarFileId as p,
  addFileEntries as c,
  updateFileEntry as I,
  updateFileEntries as f,
  updateFileLocalSpeed as w,
  updateFileStats as g,
  clearFileStats as u,
  updateFileEntryClearedAll as F,
  updateFileEntryListClearedSuccess as B,
  updateFileEntryClearedAllStatus as b,
  resetFileEntries as S,
  savePendingDownloadedFiles as m,
  pauseFileDownload as x,
  resumeFileDownload as v,
  removeFileDownload as h,
  updateFileDownloadName as E,
  updateFileDownloadProgress as L,
  updateFileDownloadSpeed as D,
  setFileDownloadError as P,
  toggleFileDownloads as k,
  setFileViewer as A,
  setFileViewerLoading as M,
  setFileViewerHighResolution as C,
  setFileViewerError as R,
  resetFileViewer as T,
  setFilePlayer as V,
  closeFilePlayer as H,
  toggleFilePlayer as N,
} from "./file.action"
export const FILE_STATE_KEY = "file"
const U = {
  file: { entriesById: {}, statsById: {}, avatarFileIds: [], clearAllStatus: r.INITIAL },
  downloads: { open: !1, autoid: 1, ids: [], byId: {} },
  viewer: {
    roomId: "",
    file: null,
    type: "",
    isLoading: !0,
    isHighResolution: !1,
    errorCode: null,
  },
  player: { file: null, playing: !1 },
}
export const getFileState = (e) => e.file
export function fileReducer(e = U, t) {
  switch (t.type) {
    case c.type: {
      const o = { ...e.file.entriesById }
      for (const e of t.payload) o[e.id] || (o[e.id] = e)
      return { ...e, file: { ...e.file, entriesById: o } }
    }
    case I.type: {
      const o = t.payload
      return {
        ...e,
        file: {
          ...e.file,
          entriesById: { ...e.file.entriesById, [o.id]: i(e.file.entriesById[o.id], o) },
        },
      }
    }
    case f.type: {
      const o = { ...e.file.entriesById }
      for (const e of t.payload) o[e.id] = i(o[e.id], e)
      return { ...e, file: { ...e.file, entriesById: o } }
    }
    case w.type: {
      const { fileId: o, speed: l } = t.payload,
        d = e.file.statsById[o]
      return d
        ? {
            ...e,
            file: { ...e.file, statsById: { ...e.file.statsById, [o]: { ...d, localSpeed: l } } },
          }
        : e
    }
    case g.type: {
      const o = t.payload
      if (!Array.isArray(o) || !o.length) return e
      const l = {}
      let d = !1
      for (let t = 0; t < o.length; t += 1) {
        const { fileId: s, stats: i } = o[t]
        if (!i || l[s]) continue
        const a = e.file.statsById[s]
        ;((l[s] = {
          ...a,
          downloadStats: {
            blocks: i.downloadStats.blocks,
            peers: i.downloadStats.peers,
            speed: i.downloadStats.speed,
          },
          uploadStats: {
            blocks: i.uploadStats.blocks,
            peers: i.uploadStats.peers,
            speed: i.uploadStats.speed,
          },
          peers: i.peers,
          blob: i.blob,
          localSpeed: a?.localSpeed || 0,
        }),
          (d = !0))
      }
      return d ? { ...e, file: { ...e.file, statsById: { ...e.file.statsById, ...l } } } : e
    }
    case u.type: {
      const o = { ...e.file.statsById }
      return (delete o[t.payload.fileId], { ...e, file: { ...e.file, statsById: o } })
    }
    case B.type: {
      const { fileIds: o, cleared: l } = t.payload,
        d = { ...e.file.entriesById }
      for (const t of o) {
        const o = e.file.entriesById[t]
        o && (d[t] = { ...o, cleared: l })
      }
      return { ...e, file: { ...e.file, entriesById: d } }
    }
    case b.type:
      return { ...e, file: { ...e.file, clearAllStatus: t.payload } }
    case F.type: {
      const o = { ...e.file.entriesById }
      for (const l of Object.keys(e.file.entriesById))
        o[l] = { ...e.file.entriesById[l], cleared: t.payload }
      return { ...e, file: { ...e.file, entriesById: o } }
    }
    case p.type: {
      const { fileId: o } = t.payload
      return !o || e.file.avatarFileIds.includes(o)
        ? e
        : { ...e, file: { ...e.file, avatarFileIds: [...e.file.avatarFileIds, o] } }
    }
    case S.type:
      return { ...e, file: { ...e.file, entriesById: {}, statsById: {} } }
    case m.type: {
      const { roomId: o, files: l, lastDownloadId: d } = t.payload,
        s = { ...e.downloads.byId },
        i = [...e.downloads.ids]
      for (const e of l) {
        if (s[e.downloadId]) continue
        const { fileEntry: t, downloadId: l, fileId: d } = e
        ;((s[l] = {
          roomId: o,
          fileId: d,
          downloadId: l,
          fileEntry: t,
          name: t.name,
          fileName: "",
          httpLink: t.httpLink,
          mimetype: t.mimetype,
          byteLength: t.byteLength,
          byteProgress: 0,
          speed: 0,
          paused: !1,
          error: null,
        }),
          i.unshift(l))
      }
      return { ...e, downloads: { ...e.downloads, byId: s, ids: i, autoid: d, open: !0 } }
    }
    case x.type: {
      const o = t.payload,
        l = e.downloads.byId[o]
      return l
        ? {
            ...e,
            downloads: { ...e.downloads, byId: { ...e.downloads.byId, [o]: { ...l, paused: !0 } } },
          }
        : e
    }
    case v.type: {
      const o = t.payload,
        l = e.downloads.byId[o]
      return l
        ? {
            ...e,
            downloads: { ...e.downloads, byId: { ...e.downloads.byId, [o]: { ...l, paused: !1 } } },
          }
        : e
    }
    case h.type: {
      const o = t.payload,
        l = { ...e.downloads.byId }
      return (
        delete l[o],
        {
          ...e,
          downloads: { ...e.downloads, ids: e.downloads.ids.filter((e) => e !== o), byId: l },
        }
      )
    }
    case E.type: {
      const { downloadId: o, fileName: l } = t.payload,
        d = e.downloads.byId[o]
      return d
        ? {
            ...e,
            downloads: {
              ...e.downloads,
              byId: { ...e.downloads.byId, [o]: { ...d, fileName: l } },
            },
          }
        : e
    }
    case L.type: {
      const { downloadId: o, byteProgress: l } = t.payload,
        d = e.downloads.byId[o]
      return d
        ? {
            ...e,
            downloads: {
              ...e.downloads,
              byId: { ...e.downloads.byId, [o]: { ...d, byteProgress: l } },
            },
          }
        : e
    }
    case D.type: {
      const { downloadId: o, speed: l } = t.payload,
        d = e.downloads.byId[o]
      return d
        ? {
            ...e,
            downloads: { ...e.downloads, byId: { ...e.downloads.byId, [o]: { ...d, speed: l } } },
          }
        : e
    }
    case P.type: {
      const { downloadId: o, error: l } = t.payload,
        d = e.downloads.byId[o]
      return d
        ? {
            ...e,
            downloads: { ...e.downloads, byId: { ...e.downloads.byId, [o]: { ...d, error: l } } },
          }
        : e
    }
    case k.type: {
      const o = "boolean" == typeof t.payload ? t.payload : !e.downloads.open
      return { ...e, downloads: { ...e.downloads, open: o } }
    }
    case A.type: {
      const { roomId: o = "", file: l, type: d } = t.payload
      return {
        ...e,
        viewer: { ...e.viewer, roomId: o, file: l, type: d, isHighResolution: !1, errorCode: null },
      }
    }
    case M.type:
      return { ...e, viewer: { ...e.viewer, isLoading: t.payload, errorCode: null } }
    case C.type:
      return {
        ...e,
        viewer: { ...e.viewer, isLoading: !0, isHighResolution: t.payload, errorCode: null },
      }
    case R.type:
      return { ...e, viewer: { ...e.viewer, isLoading: !1, errorCode: t.payload.errorCode } }
    case T.type:
      return { ...e, viewer: U.viewer }
    case V.type:
      return { ...e, player: { ...e.player, file: t.payload.file, playing: !0 } }
    case H.type:
      return { ...e, player: U.player }
    case N.type: {
      const o = void 0 === t.payload ? !e.player.playing : t.payload
      return { ...e, player: { ...e.player, playing: o } }
    }
    case y.type: {
      const o = { ...e.file.entriesById }
      return (
        t.payload.fileIds.forEach((e) => delete o[e]),
        { ...e, file: { ...e.file, entriesById: o } }
      )
    }
    case n.type: {
      const o = t.payload.files
      if (!o) return e
      let l = null
      for (let t = 0; t < o.length; t += 1) {
        const d = o[t],
          a = e.file.entriesById[d.id]
        a
          ? s(a.preview?.medium, d.preview?.medium) &&
            (l || (l = { ...e.file.entriesById }), (l[d.id] = i(a, d)))
          : (l || (l = { ...e.file.entriesById }), (l[d.id] = d))
      }
      return l ? { ...e, file: { ...e.file, entriesById: l } } : e
    }
    default:
      return e
  }
}
export const getFileEntriesById = (e) => getFileState(e).file.entriesById
export const getAvatarFileIds = (e) => getFileState(e).file.avatarFileIds
export const getFileEntry = (e, t) => getFileEntriesById(e)[l(t.pointer)]
export const getFileEntryById = (e, t) => getFileEntriesById(e)[t]
export const makeGetFileEntriesByIds = (o) =>
  e(getFileEntriesById, (e) => (o?.length ? o.map((t) => e[t]).filter(Boolean) : t))
export const getFileStatsById = (e) => getFileState(e).file.statsById
export const getFileStats = (e, t) => getFileStatsById(e)[t]
export const getFileClearAllStatus = (e) => getFileState(e).file.clearAllStatus
export const getFileDownloadsOpen = (e) => getFileState(e).downloads.open
export const getFileDownloadsCount = (e) => getFileState(e).downloads.ids.length
export const getFileDownloadsNextId = (e) => getFileState(e).downloads.autoid
export const getFileDownloadsIds = (e) => getFileState(e).downloads.ids
export const getFileDownloadsById = (e) => getFileState(e).downloads.byId
export const getFileDownload = (e, t) => getFileDownloadsById(e)[t]
export const getFileMimeType = (e, t) => getFileEntryById(e, t)?.mimetype || ""
export const getFileSmall = e(getFileEntryById, (e) => ({ ...e, httpLinkPreview: d(e, a.SMALL) }))
export const getFileMedium = e(getFileEntryById, (e) => ({ ...e, httpLinkPreview: d(e, a.MEDIUM) }))
export const getFileLarge = e(getFileEntryById, (e) => ({ ...e, httpLinkPreview: d(e, a.LARGE) }))
export const getShouldShowChatPreview = e(
  getFileEntryById,
  (e) => "image/svg+xml" === e?.mimetype || Boolean(d(e, a.MEDIUM) && o(e)),
)
export const getShouldFileTilePreview = e(
  getFileEntryById,
  (e) => Boolean(d(e, a.MEDIUM) || d(e, a.SMALL)) && o(e),
)
export const getFileDownloadsByteProgress = (e, t) =>
  getFileState(e).downloads.byId[t]?.byteProgress
export const getFileDownloadsProgressTotal = e(
  getFileDownloadsIds,
  getFileDownloadsById,
  (e, t) => {
    const o = e.reduce((e, o) => e + (t[o].byteProgress || 0), 0),
      l = e.reduce((e, o) => e + (t[o].byteLength || 0), 0)
    return 0 === l ? 0 : Math.round((o / l) * 100)
  },
)
export const getFileDownloadsPaused = (e, t) => getFileState(e).downloads.byId[t]?.paused
export const getFileViewerRoomId = (e) => getFileState(e).viewer.roomId
export const getFileViewerFile = (e) => getFileState(e).viewer.file
export const getFileViewerType = (e) => getFileState(e).viewer.type
export const getFileViewerLoading = (e) => getFileState(e).viewer.isLoading
export const getFileViewerHighResolution = (e) => getFileState(e).viewer.isHighResolution
export const getFileViewerError = (e) => getFileState(e).viewer.errorCode
export const getFilePlayerFile = (e) => getFileState(e).player.file
export const getFilePlayerPlaying = (e) => getFileState(e).player.playing