lbry-redux/src/redux/selectors/file_info.js
2019-11-14 12:59:37 -05:00

252 lines
6.7 KiB
JavaScript

import {
selectClaimsByUri,
selectIsFetchingClaimListMine,
selectMyClaims,
selectClaimsById,
makeSelectContentTypeForUri,
makeSelectClaimForUri,
} from 'redux/selectors/claims';
import { createSelector } from 'reselect';
import { buildURI } from 'lbryURI';
import Lbry from 'lbry';
import { PAGE_SIZE } from 'constants/claim';
export const selectState = state => state.fileInfo || {};
export const selectFileInfosByOutpoint = createSelector(
selectState,
state => state.byOutpoint || {}
);
export const selectIsFetchingFileList = createSelector(
selectState,
state => state.isFetchingFileList
);
export const selectIsFetchingFileListDownloadedOrPublished = createSelector(
selectIsFetchingFileList,
selectIsFetchingClaimListMine,
(isFetchingFileList, isFetchingClaimListMine) => isFetchingFileList || isFetchingClaimListMine
);
export const makeSelectFileInfoForUri = uri =>
createSelector(
selectClaimsByUri,
selectFileInfosByOutpoint,
(claims, byOutpoint) => {
const claim = claims[uri];
const outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined;
return outpoint ? byOutpoint[outpoint] : undefined;
}
);
export const selectDownloadingByOutpoint = createSelector(
selectState,
state => state.downloadingByOutpoint || {}
);
export const makeSelectDownloadingForUri = uri =>
createSelector(
selectDownloadingByOutpoint,
makeSelectFileInfoForUri(uri),
(byOutpoint, fileInfo) => {
if (!fileInfo) return false;
return byOutpoint[fileInfo.outpoint];
}
);
export const selectUrisLoading = createSelector(
selectState,
state => state.fetching || {}
);
export const makeSelectLoadingForUri = uri =>
createSelector(
selectUrisLoading,
makeSelectClaimForUri(uri),
(fetchingByOutpoint, claim) => {
if (!claim) {
return false;
}
const { txid, nout } = claim;
const outpoint = `${txid}:${nout}`;
const isFetching = fetchingByOutpoint[outpoint];
return isFetching;
}
);
export const selectFileInfosDownloaded = createSelector(
selectFileInfosByOutpoint,
selectMyClaims,
(byOutpoint, myClaims) =>
Object.values(byOutpoint)
.reverse()
.filter(fileInfo => {
const myClaimIds = myClaims.map(claim => claim.claim_id);
return (
fileInfo &&
myClaimIds.indexOf(fileInfo.claim_id) === -1 &&
(fileInfo.completed || fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0)
);
})
);
// export const selectFileInfoForUri = (state, props) => {
// const claims = selectClaimsByUri(state),
// claim = claims[props.uri],
// fileInfos = selectAllFileInfos(state),
// outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined;
// return outpoint && fileInfos ? fileInfos[outpoint] : undefined;
// };
export const selectDownloadingFileInfos = createSelector(
selectDownloadingByOutpoint,
selectFileInfosByOutpoint,
(downloadingByOutpoint, fileInfosByOutpoint) => {
const outpoints = Object.keys(downloadingByOutpoint);
const fileInfos = [];
outpoints.forEach(outpoint => {
const fileInfo = fileInfosByOutpoint[outpoint];
if (fileInfo) fileInfos.push(fileInfo);
});
return fileInfos;
}
);
export const selectTotalDownloadProgress = createSelector(
selectDownloadingFileInfos,
fileInfos => {
const progress = [];
fileInfos.forEach(fileInfo => {
progress.push((fileInfo.written_bytes / fileInfo.total_bytes) * 100);
});
const totalProgress = progress.reduce((a, b) => a + b, 0);
if (fileInfos.length > 0) return totalProgress / fileInfos.length / 100.0;
return -1;
}
);
export const selectFileListPublishedSort = createSelector(
selectState,
state => state.fileListPublishedSort
);
export const selectFileListDownloadedSort = createSelector(
selectState,
state => state.fileListDownloadedSort
);
export const selectDownloadedUris = createSelector(
selectFileInfosDownloaded,
// We should use permament_url but it doesn't exist in file_list
info => info.slice().map(claim => `lbry://${claim.claim_name}#${claim.claim_id}`)
);
export const makeSelectMediaTypeForUri = uri =>
createSelector(
makeSelectFileInfoForUri(uri),
makeSelectContentTypeForUri(uri),
(fileInfo, contentType) => {
if (!fileInfo && !contentType) {
return undefined;
}
const fileName = fileInfo && fileInfo.file_name;
return Lbry.getMediaType(contentType, fileName);
}
);
export const makeSelectUriIsStreamable = uri =>
createSelector(
makeSelectMediaTypeForUri(uri),
mediaType => {
const isStreamable = ['audio', 'video', 'image'].indexOf(mediaType) !== -1;
return isStreamable;
}
);
export const makeSelectDownloadPathForUri = uri =>
createSelector(
makeSelectFileInfoForUri(uri),
fileInfo => {
return fileInfo && fileInfo.download_path;
}
);
export const makeSelectFilePartlyDownloaded = uri =>
createSelector(
makeSelectFileInfoForUri(uri),
fileInfo => {
if (!fileInfo) {
return false;
}
return fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0;
}
);
export const makeSelectFileNameForUri = uri =>
createSelector(
makeSelectFileInfoForUri(uri),
fileInfo => {
return fileInfo && fileInfo.file_name;
}
);
export const selectDownloadUrlsCount = createSelector(
selectDownloadedUris,
uris => uris.length
);
function filterFileInfos(fileInfos, query) {
if (query) {
const queryMatchRegExp = new RegExp(query, 'i');
return fileInfos.filter(fileInfo => {
const { metadata } = fileInfo;
return (
(metadata.title && metadata.title.match(queryMatchRegExp)) ||
(fileInfo.channel_name && fileInfo.channel_name.match(queryMatchRegExp)) ||
(fileInfo.claim_name && fileInfo.claim_name.match(queryMatchRegExp))
);
});
}
return fileInfos;
}
export const makeSelectSearchDownloadUrlsForPage = (query, page = 1) =>
createSelector(
selectFileInfosDownloaded,
fileInfos => {
const matchingFileInfos = filterFileInfos(fileInfos, query);
const start = (Number(page) - 1) * Number(PAGE_SIZE);
const end = Number(page) * Number(PAGE_SIZE);
return matchingFileInfos && matchingFileInfos.length
? matchingFileInfos.slice(start, end).map(fileInfo =>
buildURI({
streamName: fileInfo.claim_name,
channelName: fileInfo.channel_name,
channelClaimId: fileInfo.channel_claim_id,
})
)
: [];
}
);
export const makeSelectSearchDownloadUrlsCount = query =>
createSelector(
selectFileInfosDownloaded,
fileInfos => {
return fileInfos && fileInfos.length ? filterFileInfos(fileInfos, query).length : 0;
}
);