Range request support for desktop #176

Merged
neb-b merged 4 commits from range-request into master 2019-08-13 19:33:59 +02:00
17 changed files with 334 additions and 270 deletions

348
dist/bundle.es.js vendored
View file

@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
require('proxy-polyfill'); require('proxy-polyfill');
var mime = _interopDefault(require('mime'));
var reselect = require('reselect'); var reselect = require('reselect');
var uuid = _interopDefault(require('uuid/v4')); var uuid = _interopDefault(require('uuid/v4'));
var fs = _interopDefault(require('fs')); var fs = _interopDefault(require('fs'));
@ -136,6 +137,7 @@ const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED'; const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED';
const FETCH_FILE_INFO_STARTED = 'FETCH_FILE_INFO_STARTED'; const FETCH_FILE_INFO_STARTED = 'FETCH_FILE_INFO_STARTED';
const FETCH_FILE_INFO_COMPLETED = 'FETCH_FILE_INFO_COMPLETED'; const FETCH_FILE_INFO_COMPLETED = 'FETCH_FILE_INFO_COMPLETED';
const FETCH_FILE_INFO_FAILED = 'FETCH_FILE_INFO_FAILED';
const LOADING_VIDEO_STARTED = 'LOADING_VIDEO_STARTED'; const LOADING_VIDEO_STARTED = 'LOADING_VIDEO_STARTED';
const LOADING_VIDEO_COMPLETED = 'LOADING_VIDEO_COMPLETED'; const LOADING_VIDEO_COMPLETED = 'LOADING_VIDEO_COMPLETED';
const LOADING_VIDEO_FAILED = 'LOADING_VIDEO_FAILED'; const LOADING_VIDEO_FAILED = 'LOADING_VIDEO_FAILED';
@ -152,9 +154,6 @@ const PURCHASE_URI_STARTED = 'PURCHASE_URI_STARTED';
const PURCHASE_URI_COMPLETED = 'PURCHASE_URI_COMPLETED'; const PURCHASE_URI_COMPLETED = 'PURCHASE_URI_COMPLETED';
const PURCHASE_URI_FAILED = 'PURCHASE_URI_FAILED'; const PURCHASE_URI_FAILED = 'PURCHASE_URI_FAILED';
const DELETE_PURCHASED_URI = 'DELETE_PURCHASED_URI'; const DELETE_PURCHASED_URI = 'DELETE_PURCHASED_URI';
const LOADING_FILE_STARTED = 'LOADING_FILE_STARTED';
const LOADING_FILE_COMPLETED = 'LOADING_FILE_COMPLETED';
const LOADING_FILE_FAILED = 'LOADING_FILE_FAILED';
// Search // Search
const SEARCH_START = 'SEARCH_START'; const SEARCH_START = 'SEARCH_START';
@ -365,6 +364,7 @@ var action_types = /*#__PURE__*/Object.freeze({
FILE_LIST_SUCCEEDED: FILE_LIST_SUCCEEDED, FILE_LIST_SUCCEEDED: FILE_LIST_SUCCEEDED,
FETCH_FILE_INFO_STARTED: FETCH_FILE_INFO_STARTED, FETCH_FILE_INFO_STARTED: FETCH_FILE_INFO_STARTED,
FETCH_FILE_INFO_COMPLETED: FETCH_FILE_INFO_COMPLETED, FETCH_FILE_INFO_COMPLETED: FETCH_FILE_INFO_COMPLETED,
FETCH_FILE_INFO_FAILED: FETCH_FILE_INFO_FAILED,
LOADING_VIDEO_STARTED: LOADING_VIDEO_STARTED, LOADING_VIDEO_STARTED: LOADING_VIDEO_STARTED,
LOADING_VIDEO_COMPLETED: LOADING_VIDEO_COMPLETED, LOADING_VIDEO_COMPLETED: LOADING_VIDEO_COMPLETED,
LOADING_VIDEO_FAILED: LOADING_VIDEO_FAILED, LOADING_VIDEO_FAILED: LOADING_VIDEO_FAILED,
@ -381,9 +381,6 @@ var action_types = /*#__PURE__*/Object.freeze({
PURCHASE_URI_COMPLETED: PURCHASE_URI_COMPLETED, PURCHASE_URI_COMPLETED: PURCHASE_URI_COMPLETED,
PURCHASE_URI_FAILED: PURCHASE_URI_FAILED, PURCHASE_URI_FAILED: PURCHASE_URI_FAILED,
DELETE_PURCHASED_URI: DELETE_PURCHASED_URI, DELETE_PURCHASED_URI: DELETE_PURCHASED_URI,
LOADING_FILE_STARTED: LOADING_FILE_STARTED,
LOADING_FILE_COMPLETED: LOADING_FILE_COMPLETED,
LOADING_FILE_FAILED: LOADING_FILE_FAILED,
SEARCH_START: SEARCH_START, SEARCH_START: SEARCH_START,
SEARCH_SUCCESS: SEARCH_SUCCESS, SEARCH_SUCCESS: SEARCH_SUCCESS,
SEARCH_FAIL: SEARCH_FAIL, SEARCH_FAIL: SEARCH_FAIL,
@ -696,23 +693,32 @@ const Lbry = {
}, },
// Returns a human readable media type based on the content type or extension of a file that is returned by the sdk // Returns a human readable media type based on the content type or extension of a file that is returned by the sdk
getMediaType: (contentType, extname) => { getMediaType: (contentType, fileName) => {
if (extname) { const formats = [[/\.(mp4|m4v|webm|flv|f4v|ogv)$/i, 'video'], [/\.(mp3|m4a|aac|wav|flac|ogg|opus)$/i, 'audio'], [/\.(h|go|ja|java|js|jsx|c|cpp|cs|css|rb|scss|sh|php|py)$/i, 'script'], [/\.(json|csv|txt|log|md|markdown|docx|pdf|xml|yml|yaml)$/i, 'document'], [/\.(pdf|odf|doc|docx|epub|org|rtf)$/i, 'e-book'], [/\.(stl|obj|fbx|gcode)$/i, '3D-file'], [/\.(cbr|cbt|cbz)$/i, 'comic-book']];
const formats = [[/^(mp4|m4v|webm|flv|f4v|ogv)$/i, 'video'], [/^(mp3|m4a|aac|wav|flac|ogg|opus)$/i, 'audio'], [/^(html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org)$/i, 'document'], [/^(stl|obj|fbx|gcode)$/i, '3D-file']];
const extName = mime.getExtension(contentType);
const fileExt = extName ? `.${extName}` : null;
const testString = fileName || fileExt;
// Get mediaType from file extension
if (testString) {
const res = formats.reduce((ret, testpair) => { const res = formats.reduce((ret, testpair) => {
switch (testpair[0].test(ret)) { const [regex, mediaType] = testpair;
case true:
return testpair[1]; return regex.test(ret) ? mediaType : ret;
default: }, testString);
return ret;
if (res !== testString) return res;
} }
}, extname);
return res === extname ? 'unknown' : res; // Get mediaType from contentType
} else if (contentType) { if (contentType) {
// $FlowFixMe const matches = /^[^/]+/.exec(contentType);
return (/^[^/]+/.exec(contentType)[0] if (matches) {
); return matches[0];
} }
}
return 'unknown'; return 'unknown';
}, },
@ -2447,7 +2453,7 @@ const makeSelectLoadingForUri = uri => reselect.createSelector(selectUrisLoading
const selectFileInfosDownloaded = reselect.createSelector(selectFileInfosByOutpoint, selectMyClaims, (byOutpoint, myClaims) => Object.values(byOutpoint).filter(fileInfo => { const selectFileInfosDownloaded = reselect.createSelector(selectFileInfosByOutpoint, selectMyClaims, (byOutpoint, myClaims) => Object.values(byOutpoint).filter(fileInfo => {
const myClaimIds = myClaims.map(claim => claim.claim_id); const myClaimIds = myClaims.map(claim => claim.claim_id);
return fileInfo && myClaimIds.indexOf(fileInfo.claim_id) === -1 && (fileInfo.completed || fileInfo.written_bytes); return fileInfo && myClaimIds.indexOf(fileInfo.claim_id) === -1 && (fileInfo.completed || fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0);
})); }));
// export const selectFileInfoForUri = (state, props) => { // export const selectFileInfoForUri = (state, props) => {
@ -2586,6 +2592,27 @@ const selectDownloadedUris = reselect.createSelector(selectFileInfosDownloaded,
// We should use permament_url but it doesn't exist in file_list // We should use permament_url but it doesn't exist in file_list
info => info.slice().reverse().map(claim => `lbry://${claim.claim_name}#${claim.claim_id}`)); info => info.slice().reverse().map(claim => `lbry://${claim.claim_name}#${claim.claim_id}`));
const makeSelectMediaTypeForUri = uri => reselect.createSelector(makeSelectFileInfoForUri(uri), makeSelectContentTypeForUri(uri), (fileInfo, contentType) => {
if (!fileInfo && !contentType) {
return undefined;
}
const fileName = fileInfo && fileInfo.file_name;
return lbryProxy.getMediaType(contentType, fileName);
});
const makeSelectUriIsStreamable = uri => reselect.createSelector(makeSelectMediaTypeForUri(uri), mediaType => {
const isStreamable = ['audio', 'video', 'image'].indexOf(mediaType) !== -1;
return isStreamable;
});
const makeSelectDownloadPathForUri = uri => reselect.createSelector(makeSelectFileInfoForUri(uri), fileInfo => {
return fileInfo && fileInfo.download_path;
});
const makeSelectFileNameForUri = uri => reselect.createSelector(makeSelectFileInfoForUri(uri), fileInfo => {
return fileInfo && fileInfo.file_name;
});
// //
const selectState$4 = state => state.file || {}; const selectState$4 = state => state.file || {};
@ -2596,65 +2623,76 @@ const selectFailedPurchaseUris = reselect.createSelector(selectState$4, state =>
const selectPurchasedUris = reselect.createSelector(selectState$4, state => state.purchasedUris); const selectPurchasedUris = reselect.createSelector(selectState$4, state => state.purchasedUris);
const selectPurchasedStreamingUrls = reselect.createSelector(selectState$4, state => state.purchasedStreamingUrls);
const selectLastPurchasedUri = reselect.createSelector(selectState$4, state => state.purchasedUris.length > 0 ? state.purchasedUris[state.purchasedUris.length - 1] : null); const selectLastPurchasedUri = reselect.createSelector(selectState$4, state => state.purchasedUris.length > 0 ? state.purchasedUris[state.purchasedUris.length - 1] : null);
const makeSelectStreamingUrlForUri = uri => reselect.createSelector(selectPurchasedStreamingUrls, streamingUrls => streamingUrls && streamingUrls[uri]); const makeSelectStreamingUrlForUri = uri => reselect.createSelector(makeSelectFileInfoForUri(uri), fileInfo => {
return fileInfo && fileInfo.streaming_url;
});
// //
function doFileGet(uri, saveFile = true) { function doFileGet(uri, saveFile = true, onSuccess) {
return dispatch => { return (dispatch, getState) => {
const state = getState();
const { nout, txid } = makeSelectClaimForUri(uri)(state);
const outpoint = `${txid}:${nout}`;
dispatch({ dispatch({
type: LOADING_FILE_STARTED, type: FETCH_FILE_INFO_STARTED,
data: { data: {
uri outpoint
} }
}); });
// set save_file argument to True to save the file (old behaviour) // set save_file argument to True to save the file (old behaviour)
lbryProxy.get({ uri, save_file: saveFile }).then(streamInfo => { lbryProxy.get({ uri, save_file: saveFile }).then(streamInfo => {
const timeout = streamInfo === null || typeof streamInfo !== 'object'; const timeout = streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout';
if (timeout) { if (timeout) {
dispatch({ dispatch({
type: LOADING_FILE_FAILED, type: FETCH_FILE_INFO_FAILED,
data: { uri } data: { outpoint }
});
dispatch({
type: PURCHASE_URI_FAILED,
data: { uri }
}); });
dispatch(doToast({ message: `File timeout for uri ${uri}`, isError: true })); dispatch(doToast({ message: `File timeout for uri ${uri}`, isError: true }));
} else { } else {
// purchase was completed successfully // purchase was completed successfully
const { streaming_url: streamingUrl } = streamInfo;
dispatch({ dispatch({
type: PURCHASE_URI_COMPLETED, type: PURCHASE_URI_COMPLETED,
data: { uri, streamingUrl: !saveFile && streamingUrl ? streamingUrl : null }
});
}
}).catch(() => {
dispatch({
type: LOADING_FILE_FAILED,
data: { uri } data: { uri }
}); });
dispatch({
type: FETCH_FILE_INFO_COMPLETED,
data: {
fileInfo: streamInfo,
outpoint: streamInfo.outpoint
}
});
if (onSuccess) {
onSuccess(streamInfo);
}
}
}).catch(() => {
dispatch({ dispatch({
type: PURCHASE_URI_FAILED, type: PURCHASE_URI_FAILED,
data: { uri } data: { uri }
}); });
dispatch({
type: FETCH_FILE_INFO_FAILED,
data: { outpoint }
});
dispatch(doToast({ dispatch(doToast({
message: `Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.com/faq/support for support.`, message: `Failed to view ${uri}, please try again. If this problem persists, visit https://lbry.com/faq/support for support.`,
isError: true isError: true
})); }));
}); });
}; };
} }
function doPurchaseUri(uri, costInfo, saveFile = true) { function doPurchaseUri(uri, costInfo, saveFile = true, onSuccess) {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch({ dispatch({
type: PURCHASE_URI_STARTED, type: PURCHASE_URI_STARTED,
@ -2685,7 +2723,7 @@ function doPurchaseUri(uri, costInfo, saveFile = true) {
return; return;
} }
dispatch(doFileGet(uri, saveFile)); dispatch(doFileGet(uri, saveFile, onSuccess));
}; };
} }
@ -3831,8 +3869,6 @@ function contentReducer(state = defaultState$2, action) {
return state; return state;
} }
var _extends$8 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
const reducers$2 = {}; const reducers$2 = {};
const defaultState$3 = { const defaultState$3 = {
fileListPublishedSort: DATE_NEW, fileListPublishedSort: DATE_NEW,
@ -3887,20 +3923,27 @@ reducers$2[FETCH_FILE_INFO_COMPLETED] = (state, action) => {
}); });
}; };
reducers$2[FETCH_FILE_INFO_FAILED] = (state, action) => {
const { outpoint } = action.data;
const newFetching = Object.assign({}, state.fetching);
delete newFetching[outpoint];
return Object.assign({}, state, {
fetching: newFetching
});
};
reducers$2[DOWNLOADING_STARTED] = (state, action) => { reducers$2[DOWNLOADING_STARTED] = (state, action) => {
const { uri, outpoint, fileInfo } = action.data; const { uri, outpoint, fileInfo } = action.data;
const newByOutpoint = Object.assign({}, state.byOutpoint); const newByOutpoint = Object.assign({}, state.byOutpoint);
const newDownloading = Object.assign({}, state.downloadingByOutpoint); const newDownloading = Object.assign({}, state.downloadingByOutpoint);
const newLoading = Object.assign({}, state.urisLoading);
newDownloading[outpoint] = true; newDownloading[outpoint] = true;
newByOutpoint[outpoint] = fileInfo; newByOutpoint[outpoint] = fileInfo;
delete newLoading[uri];
return Object.assign({}, state, { return Object.assign({}, state, {
downloadingByOutpoint: newDownloading, downloadingByOutpoint: newDownloading,
urisLoading: newLoading,
byOutpoint: newByOutpoint byOutpoint: newByOutpoint
}); });
}; };
@ -3921,7 +3964,7 @@ reducers$2[DOWNLOADING_PROGRESSED] = (state, action) => {
}; };
reducers$2[DOWNLOADING_CANCELED] = (state, action) => { reducers$2[DOWNLOADING_CANCELED] = (state, action) => {
const { outpoint } = action.data; const { uri, outpoint } = action.data;
const newDownloading = Object.assign({}, state.downloadingByOutpoint); const newDownloading = Object.assign({}, state.downloadingByOutpoint);
delete newDownloading[outpoint]; delete newDownloading[outpoint];
@ -3961,36 +4004,6 @@ reducers$2[FILE_DELETE] = (state, action) => {
}); });
}; };
reducers$2[LOADING_VIDEO_STARTED] = (state, action) => {
const { uri } = action.data;
const newLoading = Object.assign({}, state.urisLoading);
newLoading[uri] = true;
const newErrors = _extends$8({}, state.errors);
if (uri in newErrors) delete newErrors[uri];
return Object.assign({}, state, {
urisLoading: newLoading,
errors: _extends$8({}, newErrors)
});
};
reducers$2[LOADING_VIDEO_FAILED] = (state, action) => {
const { uri } = action.data;
const newLoading = Object.assign({}, state.urisLoading);
delete newLoading[uri];
const newErrors = _extends$8({}, state.errors);
newErrors[uri] = true;
return Object.assign({}, state, {
urisLoading: newLoading,
errors: _extends$8({}, newErrors)
});
};
reducers$2[SET_FILE_LIST_SORT] = (state, action) => { reducers$2[SET_FILE_LIST_SORT] = (state, action) => {
const pageSortStates = { const pageSortStates = {
[PUBLISHED]: 'fileListPublishedSort', [PUBLISHED]: 'fileListPublishedSort',
@ -4010,13 +4023,12 @@ function fileInfoReducer(state = defaultState$3, action) {
return state; return state;
} }
var _extends$9 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _extends$8 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
const reducers$3 = {}; const reducers$3 = {};
const defaultState$4 = { const defaultState$4 = {
failedPurchaseUris: [], failedPurchaseUris: [],
purchasedUris: [], purchasedUris: [],
purchasedStreamingUrls: {},
purchaseUriErrorMessage: '' purchaseUriErrorMessage: ''
}; };
@ -4027,17 +4039,16 @@ reducers$3[PURCHASE_URI_STARTED] = (state, action) => {
newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1); newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1);
} }
return _extends$9({}, state, { return _extends$8({}, state, {
failedPurchaseUris: newFailedPurchaseUris, failedPurchaseUris: newFailedPurchaseUris,
purchaseUriErrorMessage: '' purchaseUriErrorMessage: ''
}); });
}; };
reducers$3[PURCHASE_URI_COMPLETED] = (state, action) => { reducers$3[PURCHASE_URI_COMPLETED] = (state, action) => {
const { uri, streamingUrl } = action.data; const { uri } = action.data;
const newPurchasedUris = state.purchasedUris.slice(); const newPurchasedUris = state.purchasedUris.slice();
const newFailedPurchaseUris = state.failedPurchaseUris.slice(); const newFailedPurchaseUris = state.failedPurchaseUris.slice();
const newPurchasedStreamingUrls = Object.assign({}, state.purchasedStreamingUrls);
if (!newPurchasedUris.includes(uri)) { if (!newPurchasedUris.includes(uri)) {
newPurchasedUris.push(uri); newPurchasedUris.push(uri);
@ -4045,14 +4056,10 @@ reducers$3[PURCHASE_URI_COMPLETED] = (state, action) => {
if (newFailedPurchaseUris.includes(uri)) { if (newFailedPurchaseUris.includes(uri)) {
newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1); newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1);
} }
if (streamingUrl) {
newPurchasedStreamingUrls[uri] = streamingUrl;
}
return _extends$9({}, state, { return _extends$8({}, state, {
failedPurchaseUris: newFailedPurchaseUris, failedPurchaseUris: newFailedPurchaseUris,
purchasedUris: newPurchasedUris, purchasedUris: newPurchasedUris,
purchasedStreamingUrls: newPurchasedStreamingUrls,
purchaseUriErrorMessage: '' purchaseUriErrorMessage: ''
}); });
}; };
@ -4065,7 +4072,7 @@ reducers$3[PURCHASE_URI_FAILED] = (state, action) => {
newFailedPurchaseUris.push(uri); newFailedPurchaseUris.push(uri);
} }
return _extends$9({}, state, { return _extends$8({}, state, {
failedPurchaseUris: newFailedPurchaseUris, failedPurchaseUris: newFailedPurchaseUris,
purchaseUriErrorMessage: error purchaseUriErrorMessage: error
}); });
@ -4078,7 +4085,7 @@ reducers$3[DELETE_PURCHASED_URI] = (state, action) => {
newPurchasedUris.splice(newPurchasedUris.indexOf(uri), 1); newPurchasedUris.splice(newPurchasedUris.indexOf(uri), 1);
} }
return _extends$9({}, state, { return _extends$8({}, state, {
purchasedUris: newPurchasedUris purchasedUris: newPurchasedUris
}); });
}; };
@ -4089,7 +4096,7 @@ function fileReducer(state = defaultState$4, action) {
return state; return state;
} }
var _extends$a = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _extends$9 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
const defaultState$5 = { const defaultState$5 = {
notifications: [], notifications: [],
@ -4104,7 +4111,7 @@ const notificationsReducer = handleActions({
const newToasts = state.toasts.slice(); const newToasts = state.toasts.slice();
newToasts.push(toast); newToasts.push(toast);
return _extends$a({}, state, { return _extends$9({}, state, {
toasts: newToasts toasts: newToasts
}); });
}, },
@ -4112,7 +4119,7 @@ const notificationsReducer = handleActions({
const newToasts = state.toasts.slice(); const newToasts = state.toasts.slice();
newToasts.shift(); newToasts.shift();
return _extends$a({}, state, { return _extends$9({}, state, {
toasts: newToasts toasts: newToasts
}); });
}, },
@ -4123,7 +4130,7 @@ const notificationsReducer = handleActions({
const newNotifications = state.notifications.slice(); const newNotifications = state.notifications.slice();
newNotifications.push(notification); newNotifications.push(notification);
return _extends$a({}, state, { return _extends$9({}, state, {
notifications: newNotifications notifications: newNotifications
}); });
}, },
@ -4134,7 +4141,7 @@ const notificationsReducer = handleActions({
notifications = notifications.map(pastNotification => pastNotification.id === notification.id ? notification : pastNotification); notifications = notifications.map(pastNotification => pastNotification.id === notification.id ? notification : pastNotification);
return _extends$a({}, state, { return _extends$9({}, state, {
notifications notifications
}); });
}, },
@ -4143,7 +4150,7 @@ const notificationsReducer = handleActions({
let newNotifications = state.notifications.slice(); let newNotifications = state.notifications.slice();
newNotifications = newNotifications.filter(notification => notification.id !== id); newNotifications = newNotifications.filter(notification => notification.id !== id);
return _extends$a({}, state, { return _extends$9({}, state, {
notifications: newNotifications notifications: newNotifications
}); });
}, },
@ -4154,7 +4161,7 @@ const notificationsReducer = handleActions({
const newErrors = state.errors.slice(); const newErrors = state.errors.slice();
newErrors.push(error); newErrors.push(error);
return _extends$a({}, state, { return _extends$9({}, state, {
errors: newErrors errors: newErrors
}); });
}, },
@ -4162,13 +4169,13 @@ const notificationsReducer = handleActions({
const newErrors = state.errors.slice(); const newErrors = state.errors.slice();
newErrors.shift(); newErrors.shift();
return _extends$a({}, state, { return _extends$9({}, state, {
errors: newErrors errors: newErrors
}); });
} }
}, defaultState$5); }, defaultState$5);
var _extends$b = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _extends$a = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _objectWithoutProperties$2(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function _objectWithoutProperties$2(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
@ -4205,17 +4212,17 @@ const defaultState$6 = {
const publishReducer = handleActions({ const publishReducer = handleActions({
[UPDATE_PUBLISH_FORM]: (state, action) => { [UPDATE_PUBLISH_FORM]: (state, action) => {
const { data } = action; const { data } = action;
return _extends$b({}, state, data); return _extends$a({}, state, data);
}, },
[CLEAR_PUBLISH]: () => _extends$b({}, defaultState$6), [CLEAR_PUBLISH]: () => _extends$a({}, defaultState$6),
[PUBLISH_START]: state => _extends$b({}, state, { [PUBLISH_START]: state => _extends$a({}, state, {
publishing: true, publishing: true,
publishSuccess: false publishSuccess: false
}), }),
[PUBLISH_FAIL]: state => _extends$b({}, state, { [PUBLISH_FAIL]: state => _extends$a({}, state, {
publishing: false publishing: false
}), }),
[PUBLISH_SUCCESS]: state => _extends$b({}, state, { [PUBLISH_SUCCESS]: state => _extends$a({}, state, {
publishing: false, publishing: false,
publishSuccess: true publishSuccess: true
}), }),
@ -4230,14 +4237,14 @@ const publishReducer = handleActions({
contentName: name contentName: name
}); });
return _extends$b({}, defaultState$6, publishData, { return _extends$a({}, defaultState$6, publishData, {
editingURI: uri, editingURI: uri,
uri: shortUri uri: shortUri
}); });
} }
}, defaultState$6); }, defaultState$6);
var _extends$c = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _extends$b = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
const defaultState$7 = { const defaultState$7 = {
isActive: false, // does the user have any typed text in the search input isActive: false, // does the user have any typed text in the search input
@ -4257,29 +4264,29 @@ const defaultState$7 = {
}; };
const searchReducer = handleActions({ const searchReducer = handleActions({
[SEARCH_START]: state => _extends$c({}, state, { [SEARCH_START]: state => _extends$b({}, state, {
searching: true searching: true
}), }),
[SEARCH_SUCCESS]: (state, action) => { [SEARCH_SUCCESS]: (state, action) => {
const { query, uris } = action.data; const { query, uris } = action.data;
return _extends$c({}, state, { return _extends$b({}, state, {
searching: false, searching: false,
urisByQuery: Object.assign({}, state.urisByQuery, { [query]: uris }) urisByQuery: Object.assign({}, state.urisByQuery, { [query]: uris })
}); });
}, },
[SEARCH_FAIL]: state => _extends$c({}, state, { [SEARCH_FAIL]: state => _extends$b({}, state, {
searching: false searching: false
}), }),
[UPDATE_SEARCH_QUERY]: (state, action) => _extends$c({}, state, { [UPDATE_SEARCH_QUERY]: (state, action) => _extends$b({}, state, {
searchQuery: action.data.query, searchQuery: action.data.query,
isActive: true isActive: true
}), }),
[UPDATE_SEARCH_SUGGESTIONS]: (state, action) => _extends$c({}, state, { [UPDATE_SEARCH_SUGGESTIONS]: (state, action) => _extends$b({}, state, {
suggestions: _extends$c({}, state.suggestions, { suggestions: _extends$b({}, state.suggestions, {
[action.data.query]: action.data.suggestions [action.data.query]: action.data.suggestions
}) })
}), }),
@ -4287,30 +4294,30 @@ const searchReducer = handleActions({
// sets isActive to false so the uri will be populated correctly if the // sets isActive to false so the uri will be populated correctly if the
// user is on a file page. The search query will still be present on any // user is on a file page. The search query will still be present on any
// other page // other page
[DISMISS_NOTIFICATION]: state => _extends$c({}, state, { [DISMISS_NOTIFICATION]: state => _extends$b({}, state, {
isActive: false isActive: false
}), }),
[SEARCH_FOCUS]: state => _extends$c({}, state, { [SEARCH_FOCUS]: state => _extends$b({}, state, {
focused: true focused: true
}), }),
[SEARCH_BLUR]: state => _extends$c({}, state, { [SEARCH_BLUR]: state => _extends$b({}, state, {
focused: false focused: false
}), }),
[UPDATE_SEARCH_OPTIONS]: (state, action) => { [UPDATE_SEARCH_OPTIONS]: (state, action) => {
const { options: oldOptions } = state; const { options: oldOptions } = state;
const newOptions = action.data; const newOptions = action.data;
const options = _extends$c({}, oldOptions, newOptions); const options = _extends$b({}, oldOptions, newOptions);
return _extends$c({}, state, { return _extends$b({}, state, {
options options
}); });
} }
}, defaultState$7); }, defaultState$7);
var _extends$d = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _extends$c = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function getDefaultKnownTags() { function getDefaultKnownTags() {
return DEFAULT_FOLLOWED_TAGS.concat(DEFAULT_KNOWN_TAGS).reduce((tagsMap, tag) => _extends$d({}, tagsMap, { return DEFAULT_FOLLOWED_TAGS.concat(DEFAULT_KNOWN_TAGS).reduce((tagsMap, tag) => _extends$c({}, tagsMap, {
[tag]: { name: tag } [tag]: { name: tag }
}), {}); }), {});
} }
@ -4333,7 +4340,7 @@ const tagsReducer = handleActions({
newFollowedTags.push(name); newFollowedTags.push(name);
} }
return _extends$d({}, state, { return _extends$c({}, state, {
followedTags: newFollowedTags followedTags: newFollowedTags
}); });
}, },
@ -4342,10 +4349,10 @@ const tagsReducer = handleActions({
const { knownTags } = state; const { knownTags } = state;
const { name } = action.data; const { name } = action.data;
let newKnownTags = _extends$d({}, knownTags); let newKnownTags = _extends$c({}, knownTags);
newKnownTags[name] = { name }; newKnownTags[name] = { name };
return _extends$d({}, state, { return _extends$c({}, state, {
knownTags: newKnownTags knownTags: newKnownTags
}); });
}, },
@ -4354,11 +4361,11 @@ const tagsReducer = handleActions({
const { knownTags, followedTags } = state; const { knownTags, followedTags } = state;
const { name } = action.data; const { name } = action.data;
let newKnownTags = _extends$d({}, knownTags); let newKnownTags = _extends$c({}, knownTags);
delete newKnownTags[name]; delete newKnownTags[name];
const newFollowedTags = followedTags.filter(tag => tag !== name); const newFollowedTags = followedTags.filter(tag => tag !== name);
return _extends$d({}, state, { return _extends$c({}, state, {
knownTags: newKnownTags, knownTags: newKnownTags,
followedTags: newFollowedTags followedTags: newFollowedTags
}); });
@ -4389,7 +4396,7 @@ const blockedReducer = handleActions({
} }
}, defaultState$9); }, defaultState$9);
var _extends$e = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _extends$d = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
const buildDraftTransaction = () => ({ const buildDraftTransaction = () => ({
amount: undefined, amount: undefined,
@ -4429,25 +4436,25 @@ const defaultState$a = {
}; };
const walletReducer = handleActions({ const walletReducer = handleActions({
[FETCH_TRANSACTIONS_STARTED]: state => _extends$e({}, state, { [FETCH_TRANSACTIONS_STARTED]: state => _extends$d({}, state, {
fetchingTransactions: true fetchingTransactions: true
}), }),
[FETCH_TRANSACTIONS_COMPLETED]: (state, action) => { [FETCH_TRANSACTIONS_COMPLETED]: (state, action) => {
const byId = _extends$e({}, state.transactions); const byId = _extends$d({}, state.transactions);
const { transactions } = action.data; const { transactions } = action.data;
transactions.forEach(transaction => { transactions.forEach(transaction => {
byId[transaction.txid] = transaction; byId[transaction.txid] = transaction;
}); });
return _extends$e({}, state, { return _extends$d({}, state, {
transactions: byId, transactions: byId,
fetchingTransactions: false fetchingTransactions: false
}); });
}, },
[FETCH_SUPPORTS_STARTED]: state => _extends$e({}, state, { [FETCH_SUPPORTS_STARTED]: state => _extends$d({}, state, {
fetchingSupports: true fetchingSupports: true
}), }),
@ -4460,7 +4467,7 @@ const walletReducer = handleActions({
byOutpoint[`${txid}:${nout}`] = transaction; byOutpoint[`${txid}:${nout}`] = transaction;
}); });
return _extends$e({}, state, { supports: byOutpoint, fetchingSupports: false }); return _extends$d({}, state, { supports: byOutpoint, fetchingSupports: false });
}, },
[ABANDON_SUPPORT_STARTED]: (state, action) => { [ABANDON_SUPPORT_STARTED]: (state, action) => {
@ -4469,7 +4476,7 @@ const walletReducer = handleActions({
currentlyAbandoning[outpoint] = true; currentlyAbandoning[outpoint] = true;
return _extends$e({}, state, { return _extends$d({}, state, {
abandoningSupportsByOutpoint: currentlyAbandoning abandoningSupportsByOutpoint: currentlyAbandoning
}); });
}, },
@ -4482,56 +4489,56 @@ const walletReducer = handleActions({
delete currentlyAbandoning[outpoint]; delete currentlyAbandoning[outpoint];
delete byOutpoint[outpoint]; delete byOutpoint[outpoint];
return _extends$e({}, state, { return _extends$d({}, state, {
supports: byOutpoint, supports: byOutpoint,
abandoningSupportsById: currentlyAbandoning abandoningSupportsById: currentlyAbandoning
}); });
}, },
[GET_NEW_ADDRESS_STARTED]: state => _extends$e({}, state, { [GET_NEW_ADDRESS_STARTED]: state => _extends$d({}, state, {
gettingNewAddress: true gettingNewAddress: true
}), }),
[GET_NEW_ADDRESS_COMPLETED]: (state, action) => { [GET_NEW_ADDRESS_COMPLETED]: (state, action) => {
const { address } = action.data; const { address } = action.data;
return _extends$e({}, state, { gettingNewAddress: false, receiveAddress: address }); return _extends$d({}, state, { gettingNewAddress: false, receiveAddress: address });
}, },
[UPDATE_BALANCE]: (state, action) => _extends$e({}, state, { [UPDATE_BALANCE]: (state, action) => _extends$d({}, state, {
balance: action.data.balance balance: action.data.balance
}), }),
[UPDATE_TOTAL_BALANCE]: (state, action) => _extends$e({}, state, { [UPDATE_TOTAL_BALANCE]: (state, action) => _extends$d({}, state, {
totalBalance: action.data.totalBalance totalBalance: action.data.totalBalance
}), }),
[CHECK_ADDRESS_IS_MINE_STARTED]: state => _extends$e({}, state, { [CHECK_ADDRESS_IS_MINE_STARTED]: state => _extends$d({}, state, {
checkingAddressOwnership: true checkingAddressOwnership: true
}), }),
[CHECK_ADDRESS_IS_MINE_COMPLETED]: state => _extends$e({}, state, { [CHECK_ADDRESS_IS_MINE_COMPLETED]: state => _extends$d({}, state, {
checkingAddressOwnership: false checkingAddressOwnership: false
}), }),
[SET_DRAFT_TRANSACTION_AMOUNT]: (state, action) => { [SET_DRAFT_TRANSACTION_AMOUNT]: (state, action) => {
const oldDraft = state.draftTransaction; const oldDraft = state.draftTransaction;
const newDraft = _extends$e({}, oldDraft, { amount: parseFloat(action.data.amount) }); const newDraft = _extends$d({}, oldDraft, { amount: parseFloat(action.data.amount) });
return _extends$e({}, state, { draftTransaction: newDraft }); return _extends$d({}, state, { draftTransaction: newDraft });
}, },
[SET_DRAFT_TRANSACTION_ADDRESS]: (state, action) => { [SET_DRAFT_TRANSACTION_ADDRESS]: (state, action) => {
const oldDraft = state.draftTransaction; const oldDraft = state.draftTransaction;
const newDraft = _extends$e({}, oldDraft, { address: action.data.address }); const newDraft = _extends$d({}, oldDraft, { address: action.data.address });
return _extends$e({}, state, { draftTransaction: newDraft }); return _extends$d({}, state, { draftTransaction: newDraft });
}, },
[SEND_TRANSACTION_STARTED]: state => { [SEND_TRANSACTION_STARTED]: state => {
const newDraftTransaction = _extends$e({}, state.draftTransaction, { sending: true }); const newDraftTransaction = _extends$d({}, state.draftTransaction, { sending: true });
return _extends$e({}, state, { draftTransaction: newDraftTransaction }); return _extends$d({}, state, { draftTransaction: newDraftTransaction });
}, },
[SEND_TRANSACTION_COMPLETED]: state => Object.assign({}, state, { [SEND_TRANSACTION_COMPLETED]: state => Object.assign({}, state, {
@ -4544,103 +4551,103 @@ const walletReducer = handleActions({
error: action.data.error error: action.data.error
}); });
return _extends$e({}, state, { draftTransaction: newDraftTransaction }); return _extends$d({}, state, { draftTransaction: newDraftTransaction });
}, },
[SUPPORT_TRANSACTION_STARTED]: state => _extends$e({}, state, { [SUPPORT_TRANSACTION_STARTED]: state => _extends$d({}, state, {
sendingSupport: true sendingSupport: true
}), }),
[SUPPORT_TRANSACTION_COMPLETED]: state => _extends$e({}, state, { [SUPPORT_TRANSACTION_COMPLETED]: state => _extends$d({}, state, {
sendingSupport: false sendingSupport: false
}), }),
[SUPPORT_TRANSACTION_FAILED]: (state, action) => _extends$e({}, state, { [SUPPORT_TRANSACTION_FAILED]: (state, action) => _extends$d({}, state, {
error: action.data.error, error: action.data.error,
sendingSupport: false sendingSupport: false
}), }),
[WALLET_STATUS_COMPLETED]: (state, action) => _extends$e({}, state, { [WALLET_STATUS_COMPLETED]: (state, action) => _extends$d({}, state, {
walletIsEncrypted: action.result walletIsEncrypted: action.result
}), }),
[WALLET_ENCRYPT_START]: state => _extends$e({}, state, { [WALLET_ENCRYPT_START]: state => _extends$d({}, state, {
walletEncryptPending: true, walletEncryptPending: true,
walletEncryptSucceded: null, walletEncryptSucceded: null,
walletEncryptResult: null walletEncryptResult: null
}), }),
[WALLET_ENCRYPT_COMPLETED]: (state, action) => _extends$e({}, state, { [WALLET_ENCRYPT_COMPLETED]: (state, action) => _extends$d({}, state, {
walletEncryptPending: false, walletEncryptPending: false,
walletEncryptSucceded: true, walletEncryptSucceded: true,
walletEncryptResult: action.result walletEncryptResult: action.result
}), }),
[WALLET_ENCRYPT_FAILED]: (state, action) => _extends$e({}, state, { [WALLET_ENCRYPT_FAILED]: (state, action) => _extends$d({}, state, {
walletEncryptPending: false, walletEncryptPending: false,
walletEncryptSucceded: false, walletEncryptSucceded: false,
walletEncryptResult: action.result walletEncryptResult: action.result
}), }),
[WALLET_DECRYPT_START]: state => _extends$e({}, state, { [WALLET_DECRYPT_START]: state => _extends$d({}, state, {
walletDecryptPending: true, walletDecryptPending: true,
walletDecryptSucceded: null, walletDecryptSucceded: null,
walletDecryptResult: null walletDecryptResult: null
}), }),
[WALLET_DECRYPT_COMPLETED]: (state, action) => _extends$e({}, state, { [WALLET_DECRYPT_COMPLETED]: (state, action) => _extends$d({}, state, {
walletDecryptPending: false, walletDecryptPending: false,
walletDecryptSucceded: true, walletDecryptSucceded: true,
walletDecryptResult: action.result walletDecryptResult: action.result
}), }),
[WALLET_DECRYPT_FAILED]: (state, action) => _extends$e({}, state, { [WALLET_DECRYPT_FAILED]: (state, action) => _extends$d({}, state, {
walletDecryptPending: false, walletDecryptPending: false,
walletDecryptSucceded: false, walletDecryptSucceded: false,
walletDecryptResult: action.result walletDecryptResult: action.result
}), }),
[WALLET_UNLOCK_START]: state => _extends$e({}, state, { [WALLET_UNLOCK_START]: state => _extends$d({}, state, {
walletUnlockPending: true, walletUnlockPending: true,
walletUnlockSucceded: null, walletUnlockSucceded: null,
walletUnlockResult: null walletUnlockResult: null
}), }),
[WALLET_UNLOCK_COMPLETED]: (state, action) => _extends$e({}, state, { [WALLET_UNLOCK_COMPLETED]: (state, action) => _extends$d({}, state, {
walletUnlockPending: false, walletUnlockPending: false,
walletUnlockSucceded: true, walletUnlockSucceded: true,
walletUnlockResult: action.result walletUnlockResult: action.result
}), }),
[WALLET_UNLOCK_FAILED]: (state, action) => _extends$e({}, state, { [WALLET_UNLOCK_FAILED]: (state, action) => _extends$d({}, state, {
walletUnlockPending: false, walletUnlockPending: false,
walletUnlockSucceded: false, walletUnlockSucceded: false,
walletUnlockResult: action.result walletUnlockResult: action.result
}), }),
[WALLET_LOCK_START]: state => _extends$e({}, state, { [WALLET_LOCK_START]: state => _extends$d({}, state, {
walletLockPending: false, walletLockPending: false,
walletLockSucceded: null, walletLockSucceded: null,
walletLockResult: null walletLockResult: null
}), }),
[WALLET_LOCK_COMPLETED]: (state, action) => _extends$e({}, state, { [WALLET_LOCK_COMPLETED]: (state, action) => _extends$d({}, state, {
walletLockPending: false, walletLockPending: false,
walletLockSucceded: true, walletLockSucceded: true,
walletLockResult: action.result walletLockResult: action.result
}), }),
[WALLET_LOCK_FAILED]: (state, action) => _extends$e({}, state, { [WALLET_LOCK_FAILED]: (state, action) => _extends$d({}, state, {
walletLockPending: false, walletLockPending: false,
walletLockSucceded: false, walletLockSucceded: false,
walletLockResult: action.result walletLockResult: action.result
}), }),
[SET_TRANSACTION_LIST_FILTER]: (state, action) => _extends$e({}, state, { [SET_TRANSACTION_LIST_FILTER]: (state, action) => _extends$d({}, state, {
transactionListFilter: action.data transactionListFilter: action.data
}), }),
[UPDATE_CURRENT_HEIGHT]: (state, action) => _extends$e({}, state, { [UPDATE_CURRENT_HEIGHT]: (state, action) => _extends$d({}, state, {
latestBlock: action.data latestBlock: action.data
}) })
}, defaultState$a); }, defaultState$a);
@ -4656,14 +4663,14 @@ const makeSelectContentPositionForUri = uri => reselect.createSelector(selectSta
return state.positions[id] ? state.positions[id][outpoint] : null; return state.positions[id] ? state.positions[id][outpoint] : null;
}); });
var _extends$f = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _extends$e = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
const selectState$7 = state => state.notifications || {}; const selectState$7 = state => state.notifications || {};
const selectToast = reselect.createSelector(selectState$7, state => { const selectToast = reselect.createSelector(selectState$7, state => {
if (state.toasts.length) { if (state.toasts.length) {
const { id, params } = state.toasts[0]; const { id, params } = state.toasts[0];
return _extends$f({ return _extends$e({
id id
}, params); }, params);
} }
@ -4842,12 +4849,15 @@ exports.makeSelectContentPositionForUri = makeSelectContentPositionForUri;
exports.makeSelectContentTypeForUri = makeSelectContentTypeForUri; exports.makeSelectContentTypeForUri = makeSelectContentTypeForUri;
exports.makeSelectCoverForUri = makeSelectCoverForUri; exports.makeSelectCoverForUri = makeSelectCoverForUri;
exports.makeSelectDateForUri = makeSelectDateForUri; exports.makeSelectDateForUri = makeSelectDateForUri;
exports.makeSelectDownloadPathForUri = makeSelectDownloadPathForUri;
exports.makeSelectDownloadingForUri = makeSelectDownloadingForUri; exports.makeSelectDownloadingForUri = makeSelectDownloadingForUri;
exports.makeSelectFetchingChannelClaims = makeSelectFetchingChannelClaims; exports.makeSelectFetchingChannelClaims = makeSelectFetchingChannelClaims;
exports.makeSelectFileInfoForUri = makeSelectFileInfoForUri; exports.makeSelectFileInfoForUri = makeSelectFileInfoForUri;
exports.makeSelectFileNameForUri = makeSelectFileNameForUri;
exports.makeSelectFirstRecommendedFileForUri = makeSelectFirstRecommendedFileForUri; exports.makeSelectFirstRecommendedFileForUri = makeSelectFirstRecommendedFileForUri;
exports.makeSelectIsUriResolving = makeSelectIsUriResolving; exports.makeSelectIsUriResolving = makeSelectIsUriResolving;
exports.makeSelectLoadingForUri = makeSelectLoadingForUri; exports.makeSelectLoadingForUri = makeSelectLoadingForUri;
exports.makeSelectMediaTypeForUri = makeSelectMediaTypeForUri;
exports.makeSelectMetadataForUri = makeSelectMetadataForUri; exports.makeSelectMetadataForUri = makeSelectMetadataForUri;
exports.makeSelectMetadataItemForUri = makeSelectMetadataItemForUri; exports.makeSelectMetadataItemForUri = makeSelectMetadataItemForUri;
exports.makeSelectNsfwCountForChannel = makeSelectNsfwCountForChannel; exports.makeSelectNsfwCountForChannel = makeSelectNsfwCountForChannel;
@ -4864,6 +4874,7 @@ exports.makeSelectThumbnailForUri = makeSelectThumbnailForUri;
exports.makeSelectTitleForUri = makeSelectTitleForUri; exports.makeSelectTitleForUri = makeSelectTitleForUri;
exports.makeSelectTotalItemsForChannel = makeSelectTotalItemsForChannel; exports.makeSelectTotalItemsForChannel = makeSelectTotalItemsForChannel;
exports.makeSelectTotalPagesForChannel = makeSelectTotalPagesForChannel; exports.makeSelectTotalPagesForChannel = makeSelectTotalPagesForChannel;
exports.makeSelectUriIsStreamable = makeSelectUriIsStreamable;
exports.normalizeURI = normalizeURI; exports.normalizeURI = normalizeURI;
exports.notificationsReducer = notificationsReducer; exports.notificationsReducer = notificationsReducer;
exports.parseQueryParams = parseQueryParams; exports.parseQueryParams = parseQueryParams;
@ -4928,7 +4939,6 @@ exports.selectPendingClaims = selectPendingClaims;
exports.selectPlayingUri = selectPlayingUri; exports.selectPlayingUri = selectPlayingUri;
exports.selectPublishFormValues = selectPublishFormValues; exports.selectPublishFormValues = selectPublishFormValues;
exports.selectPurchaseUriErrorMessage = selectPurchaseUriErrorMessage; exports.selectPurchaseUriErrorMessage = selectPurchaseUriErrorMessage;
exports.selectPurchasedStreamingUrls = selectPurchasedStreamingUrls;
exports.selectPurchasedUris = selectPurchasedUris; exports.selectPurchasedUris = selectPurchasedUris;
exports.selectReceiveAddress = selectReceiveAddress; exports.selectReceiveAddress = selectReceiveAddress;
exports.selectRecentTransactions = selectRecentTransactions; exports.selectRecentTransactions = selectRecentTransactions;

View file

@ -38,7 +38,6 @@ declare type FileListItem = {
declare type FileState = { declare type FileState = {
failedPurchaseUris: Array<string>, failedPurchaseUris: Array<string>,
purchasedUris: Array<string>, purchasedUris: Array<string>,
purchasedStreamingUrls: {},
}; };
declare type PurchaseUriCompleted = { declare type PurchaseUriCompleted = {
@ -53,7 +52,7 @@ declare type PurchaseUriFailed = {
type: ACTIONS.PURCHASE_URI_FAILED, type: ACTIONS.PURCHASE_URI_FAILED,
data: { data: {
uri: string, uri: string,
error: any error: any,
}, },
}; };
@ -68,6 +67,6 @@ declare type PurchaseUriStarted = {
declare type DeletePurchasedUri = { declare type DeletePurchasedUri = {
type: ACTIONS.DELETE_PURCHASED_URI, type: ACTIONS.DELETE_PURCHASED_URI,
data: { data: {
uri: string uri: string,
}, },
}; };

View file

@ -68,7 +68,7 @@ declare type ResolveResponse = {
[string]: Claim | { error?: {} }, [string]: Claim | { error?: {} },
}; };
declare type GetResponse = FileListItem; declare type GetResponse = FileListItem & { error?: string };
declare type GenericTxResponse = { declare type GenericTxResponse = {
height: number, height: number,

4
dist/flow-typed/mime.js vendored Normal file
View file

@ -0,0 +1,4 @@
// @flow
declare module 'mime' {
declare module.exports: any;
}

5
flow-typed/File.js vendored
View file

@ -38,7 +38,6 @@ declare type FileListItem = {
declare type FileState = { declare type FileState = {
failedPurchaseUris: Array<string>, failedPurchaseUris: Array<string>,
purchasedUris: Array<string>, purchasedUris: Array<string>,
purchasedStreamingUrls: {},
}; };
declare type PurchaseUriCompleted = { declare type PurchaseUriCompleted = {
@ -53,7 +52,7 @@ declare type PurchaseUriFailed = {
type: ACTIONS.PURCHASE_URI_FAILED, type: ACTIONS.PURCHASE_URI_FAILED,
data: { data: {
uri: string, uri: string,
error: any error: any,
}, },
}; };
@ -68,6 +67,6 @@ declare type PurchaseUriStarted = {
declare type DeletePurchasedUri = { declare type DeletePurchasedUri = {
type: ACTIONS.DELETE_PURCHASED_URI, type: ACTIONS.DELETE_PURCHASED_URI,
data: { data: {
uri: string uri: string,
}, },
}; };

2
flow-typed/Lbry.js vendored
View file

@ -68,7 +68,7 @@ declare type ResolveResponse = {
[string]: Claim | { error?: {} }, [string]: Claim | { error?: {} },
}; };
declare type GetResponse = FileListItem; declare type GetResponse = FileListItem & { error?: string };
declare type GenericTxResponse = { declare type GenericTxResponse = {
height: number, height: number,

4
flow-typed/mime.js vendored Normal file
View file

@ -0,0 +1,4 @@
// @flow
declare module 'mime' {
declare module.exports: any;
}

View file

@ -28,6 +28,7 @@
"format": "prettier 'src/**/*.{js,json}' --write" "format": "prettier 'src/**/*.{js,json}' --write"
}, },
"dependencies": { "dependencies": {
"mime": "^2.4.4",
"proxy-polyfill": "0.1.6", "proxy-polyfill": "0.1.6",
"reselect": "^3.0.0", "reselect": "^3.0.0",
"uuid": "^3.3.2" "uuid": "^3.3.2"

View file

@ -111,6 +111,7 @@ export const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
export const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED'; export const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED';
export const FETCH_FILE_INFO_STARTED = 'FETCH_FILE_INFO_STARTED'; export const FETCH_FILE_INFO_STARTED = 'FETCH_FILE_INFO_STARTED';
export const FETCH_FILE_INFO_COMPLETED = 'FETCH_FILE_INFO_COMPLETED'; export const FETCH_FILE_INFO_COMPLETED = 'FETCH_FILE_INFO_COMPLETED';
export const FETCH_FILE_INFO_FAILED = 'FETCH_FILE_INFO_FAILED';
export const LOADING_VIDEO_STARTED = 'LOADING_VIDEO_STARTED'; export const LOADING_VIDEO_STARTED = 'LOADING_VIDEO_STARTED';
export const LOADING_VIDEO_COMPLETED = 'LOADING_VIDEO_COMPLETED'; export const LOADING_VIDEO_COMPLETED = 'LOADING_VIDEO_COMPLETED';
export const LOADING_VIDEO_FAILED = 'LOADING_VIDEO_FAILED'; export const LOADING_VIDEO_FAILED = 'LOADING_VIDEO_FAILED';
@ -127,9 +128,6 @@ export const PURCHASE_URI_STARTED = 'PURCHASE_URI_STARTED';
export const PURCHASE_URI_COMPLETED = 'PURCHASE_URI_COMPLETED'; export const PURCHASE_URI_COMPLETED = 'PURCHASE_URI_COMPLETED';
export const PURCHASE_URI_FAILED = 'PURCHASE_URI_FAILED'; export const PURCHASE_URI_FAILED = 'PURCHASE_URI_FAILED';
export const DELETE_PURCHASED_URI = 'DELETE_PURCHASED_URI'; export const DELETE_PURCHASED_URI = 'DELETE_PURCHASED_URI';
export const LOADING_FILE_STARTED = 'LOADING_FILE_STARTED';
export const LOADING_FILE_COMPLETED = 'LOADING_FILE_COMPLETED';
export const LOADING_FILE_FAILED = 'LOADING_FILE_FAILED';
// Search // Search
export const SEARCH_START = 'SEARCH_START'; export const SEARCH_START = 'SEARCH_START';

View file

@ -140,7 +140,6 @@ export { selectToast, selectError } from 'redux/selectors/notifications';
export { export {
selectFailedPurchaseUris, selectFailedPurchaseUris,
selectPurchasedUris, selectPurchasedUris,
selectPurchasedStreamingUrls,
selectPurchaseUriErrorMessage, selectPurchaseUriErrorMessage,
selectLastPurchasedUri, selectLastPurchasedUri,
makeSelectStreamingUrlForUri, makeSelectStreamingUrlForUri,
@ -217,6 +216,10 @@ export {
selectFileListDownloadedSort, selectFileListDownloadedSort,
selectFileListPublishedSort, selectFileListPublishedSort,
selectDownloadedUris, selectDownloadedUris,
makeSelectMediaTypeForUri,
makeSelectUriIsStreamable,
makeSelectDownloadPathForUri,
makeSelectFileNameForUri,
} from 'redux/selectors/file_info'; } from 'redux/selectors/file_info';
export { export {

View file

@ -1,5 +1,6 @@
// @flow // @flow
import 'proxy-polyfill'; import 'proxy-polyfill';
import mime from 'mime';
const CHECK_DAEMON_STARTED_TRY_NUMBER = 200; const CHECK_DAEMON_STARTED_TRY_NUMBER = 200;
// //
@ -32,27 +33,40 @@ const Lbry: LbryTypes = {
}, },
// Returns a human readable media type based on the content type or extension of a file that is returned by the sdk // Returns a human readable media type based on the content type or extension of a file that is returned by the sdk
getMediaType: (contentType: string, extname: ?string) => { getMediaType: (contentType?: string, fileName: ?string) => {
if (extname) {
const formats = [ const formats = [
[/^(mp4|m4v|webm|flv|f4v|ogv)$/i, 'video'], [/\.(mp4|m4v|webm|flv|f4v|ogv)$/i, 'video'],
[/^(mp3|m4a|aac|wav|flac|ogg|opus)$/i, 'audio'], [/\.(mp3|m4a|aac|wav|flac|ogg|opus)$/i, 'audio'],
[/^(html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org)$/i, 'document'], [/\.(h|go|ja|java|js|jsx|c|cpp|cs|css|rb|scss|sh|php|py)$/i, 'script'],
[/^(stl|obj|fbx|gcode)$/i, '3D-file'], [/\.(json|csv|txt|log|md|markdown|docx|pdf|xml|yml|yaml)$/i, 'document'],
[/\.(pdf|odf|doc|docx|epub|org|rtf)$/i, 'e-book'],
[/\.(stl|obj|fbx|gcode)$/i, '3D-file'],
[/\.(cbr|cbt|cbz)$/i, 'comic-book'],
]; ];
const extName = mime.getExtension(contentType);
const fileExt = extName ? `.${extName}` : null;
const testString = fileName || fileExt;
// Get mediaType from file extension
neb-b commented 2019-08-06 04:28:14 +02:00 (Migrated from github.com)
Review

I guess there have been some changes to this in the desktop codebase and we never moved over. Just copy pasting this in so we can switch to it.

Android doesn't use the second argument for this function so changing it should be fine.

I guess there have been some changes to this in the desktop codebase and we never moved over. Just copy pasting this in so we can switch to it. Android doesn't use the second argument for this function so changing it should be fine.
tzarebczan commented 2019-08-06 04:53:41 +02:00 (Migrated from github.com)
Review

I also mentioned to you that the SDK now returns a stream type:

      },
      "stream_type": "video",
      ],

The mapping is here - I think it should be able to work with some small adjustments (glaringly missing are fbx/gcode, but not sure if anyone uses those): 41b866c1ee/lbry/lbry/schema/mime_types.py

I also mentioned to you that the SDK now returns a stream type: ``` ... }, "stream_type": "video", ], ``` The mapping is here - I think it should be able to work with some small adjustments (glaringly missing are fbx/gcode, but not sure if anyone uses those): https://github.com/lbryio/lbry-sdk/blob/41b866c1eeb002aaa0e42bc71734f6879d3b4457/lbry/lbry/schema/mime_types.py
if (testString) {
const res = formats.reduce((ret, testpair) => { const res = formats.reduce((ret, testpair) => {
switch (testpair[0].test(ret)) { const [regex, mediaType] = testpair;
case true:
return testpair[1]; return regex.test(ret) ? mediaType : ret;
default: }, testString);
return ret;
if (res !== testString) return res;
} }
}, extname);
return res === extname ? 'unknown' : res; // Get mediaType from contentType
} else if (contentType) { if (contentType) {
// $FlowFixMe const matches = /^[^/]+/.exec(contentType);
return /^[^/]+/.exec(contentType)[0]; if (matches) {
return matches[0];
} }
}
return 'unknown'; return 'unknown';
}, },

View file

@ -5,57 +5,70 @@ import { doToast } from 'redux/actions/notifications';
import { selectBalance } from 'redux/selectors/wallet'; import { selectBalance } from 'redux/selectors/wallet';
import { makeSelectFileInfoForUri, selectDownloadingByOutpoint } from 'redux/selectors/file_info'; import { makeSelectFileInfoForUri, selectDownloadingByOutpoint } from 'redux/selectors/file_info';
import { makeSelectStreamingUrlForUri } from 'redux/selectors/file'; import { makeSelectStreamingUrlForUri } from 'redux/selectors/file';
import { makeSelectClaimForUri } from 'redux/selectors/claims';
akinwale commented 2019-08-13 10:45:12 +02:00 (Migrated from github.com)
Review

Since doPurchaseUri also dispatches the same action, how do we differentiate between the two? I recall using a different action here because it's possible for a purchase to fail due to insufficient credits, the wallet being locked or some other condition, so get doesn't actually get called in those scenarios.

Since `doPurchaseUri` also dispatches the same action, how do we differentiate between the two? I recall using a different action here because it's possible for a purchase to fail due to insufficient credits, the wallet being locked or some other condition, so `get` doesn't actually get called in those scenarios.
neb-b commented 2019-08-13 16:57:54 +02:00 (Migrated from github.com)
Review

Ah that's a good point. I just searched for LOADING_FILE_ and didn't find anything so I figured it wasn't needed. That does make sense to have two though. I'll add it back. Maybe GET_FILE_XXX to signal that it's specifically for get calls?

Ah that's a good point. I just searched for `LOADING_FILE_` and didn't find anything so I figured it wasn't needed. That does make sense to have two though. I'll add it back. Maybe `GET_FILE_XXX` to signal that it's specifically for `get` calls?
akinwale commented 2019-08-13 17:13:46 +02:00 (Migrated from github.com)
Review

GET_FILE_XXX sounds perfect.

`GET_FILE_XXX` sounds perfect.
type Dispatch = (action: any) => any; type Dispatch = (action: any) => any;
type GetState = () => { file: FileState }; type GetState = () => { file: FileState };
export function doFileGet(uri: string, saveFile: boolean = true) { export function doFileGet(uri: string, saveFile: boolean = true, onSuccess?: GetResponse => any) {
return (dispatch: Dispatch) => { return (dispatch: Dispatch, getState: () => any) => {
const state = getState();
const { nout, txid } = makeSelectClaimForUri(uri)(state);
const outpoint = `${txid}:${nout}`;
dispatch({ dispatch({
type: ACTIONS.LOADING_FILE_STARTED, type: ACTIONS.FETCH_FILE_INFO_STARTED,
data: { data: {
uri, outpoint,
}, },
}); });
// set save_file argument to True to save the file (old behaviour) // set save_file argument to True to save the file (old behaviour)
Lbry.get({ uri, save_file: saveFile }) Lbry.get({ uri, save_file: saveFile })
.then((streamInfo: GetResponse) => { .then((streamInfo: GetResponse) => {
const timeout = streamInfo === null || typeof streamInfo !== 'object'; const timeout =
streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout';
if (timeout) { if (timeout) {
dispatch({ dispatch({
type: ACTIONS.LOADING_FILE_FAILED, type: ACTIONS.FETCH_FILE_INFO_FAILED,
data: { uri }, data: { outpoint },
});
dispatch({
type: ACTIONS.PURCHASE_URI_FAILED,
data: { uri },
}); });
dispatch(doToast({ message: `File timeout for uri ${uri}`, isError: true })); dispatch(doToast({ message: `File timeout for uri ${uri}`, isError: true }));
} else { } else {
// purchase was completed successfully // purchase was completed successfully
const { streaming_url: streamingUrl } = streamInfo;
dispatch({ dispatch({
type: ACTIONS.PURCHASE_URI_COMPLETED, type: ACTIONS.PURCHASE_URI_COMPLETED,
data: { uri, streamingUrl: !saveFile && streamingUrl ? streamingUrl : null }, data: { uri },
}); });
dispatch({
type: ACTIONS.FETCH_FILE_INFO_COMPLETED,
data: {
fileInfo: streamInfo,
outpoint: streamInfo.outpoint,
},
});
if (onSuccess) {
onSuccess(streamInfo);
}
} }
}) })
.catch(() => { .catch(() => {
dispatch({
type: ACTIONS.LOADING_FILE_FAILED,
data: { uri },
});
dispatch({ dispatch({
type: ACTIONS.PURCHASE_URI_FAILED, type: ACTIONS.PURCHASE_URI_FAILED,
data: { uri }, data: { uri },
}); });
dispatch({
type: ACTIONS.FETCH_FILE_INFO_FAILED,
data: { outpoint },
});
dispatch( dispatch(
doToast({ doToast({
message: `Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.com/faq/support for support.`, message: `Failed to view ${uri}, please try again. If this problem persists, visit https://lbry.com/faq/support for support.`,
isError: true, isError: true,
}) })
); );
@ -63,7 +76,12 @@ export function doFileGet(uri: string, saveFile: boolean = true) {
}; };
} }
export function doPurchaseUri(uri: string, costInfo: { cost: number }, saveFile: boolean = true) { export function doPurchaseUri(
uri: string,
costInfo: { cost: number },
saveFile: boolean = true,
onSuccess?: GetResponse => any
) {
return (dispatch: Dispatch, getState: GetState) => { return (dispatch: Dispatch, getState: GetState) => {
dispatch({ dispatch({
type: ACTIONS.PURCHASE_URI_STARTED, type: ACTIONS.PURCHASE_URI_STARTED,
@ -98,7 +116,7 @@ export function doPurchaseUri(uri: string, costInfo: { cost: number }, saveFile:
return; return;
} }
dispatch(doFileGet(uri, saveFile)); dispatch(doFileGet(uri, saveFile, onSuccess));
}; };
} }

View file

@ -5,7 +5,6 @@ const reducers = {};
const defaultState = { const defaultState = {
failedPurchaseUris: [], failedPurchaseUris: [],
purchasedUris: [], purchasedUris: [],
purchasedStreamingUrls: {},
purchaseUriErrorMessage: '', purchaseUriErrorMessage: '',
}; };
@ -30,10 +29,9 @@ reducers[ACTIONS.PURCHASE_URI_COMPLETED] = (
state: FileState, state: FileState,
action: PurchaseUriCompleted action: PurchaseUriCompleted
): FileState => { ): FileState => {
const { uri, streamingUrl } = action.data; const { uri } = action.data;
const newPurchasedUris = state.purchasedUris.slice(); const newPurchasedUris = state.purchasedUris.slice();
const newFailedPurchaseUris = state.failedPurchaseUris.slice(); const newFailedPurchaseUris = state.failedPurchaseUris.slice();
const newPurchasedStreamingUrls = Object.assign({}, state.purchasedStreamingUrls);
if (!newPurchasedUris.includes(uri)) { if (!newPurchasedUris.includes(uri)) {
newPurchasedUris.push(uri); newPurchasedUris.push(uri);
@ -41,15 +39,11 @@ reducers[ACTIONS.PURCHASE_URI_COMPLETED] = (
if (newFailedPurchaseUris.includes(uri)) { if (newFailedPurchaseUris.includes(uri)) {
newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1); newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1);
} }
if (streamingUrl) {
newPurchasedStreamingUrls[uri] = streamingUrl;
}
return { return {
...state, ...state,
failedPurchaseUris: newFailedPurchaseUris, failedPurchaseUris: newFailedPurchaseUris,
purchasedUris: newPurchasedUris, purchasedUris: newPurchasedUris,
purchasedStreamingUrls: newPurchasedStreamingUrls,
purchaseUriErrorMessage: '', purchaseUriErrorMessage: '',
}; };
}; };

View file

@ -57,20 +57,27 @@ reducers[ACTIONS.FETCH_FILE_INFO_COMPLETED] = (state, action) => {
}); });
}; };
reducers[ACTIONS.FETCH_FILE_INFO_FAILED] = (state, action) => {
const { outpoint } = action.data;
const newFetching = Object.assign({}, state.fetching);
delete newFetching[outpoint];
return Object.assign({}, state, {
fetching: newFetching,
});
};
reducers[ACTIONS.DOWNLOADING_STARTED] = (state, action) => { reducers[ACTIONS.DOWNLOADING_STARTED] = (state, action) => {
const { uri, outpoint, fileInfo } = action.data; const { uri, outpoint, fileInfo } = action.data;
const newByOutpoint = Object.assign({}, state.byOutpoint); const newByOutpoint = Object.assign({}, state.byOutpoint);
const newDownloading = Object.assign({}, state.downloadingByOutpoint); const newDownloading = Object.assign({}, state.downloadingByOutpoint);
const newLoading = Object.assign({}, state.urisLoading);
newDownloading[outpoint] = true; newDownloading[outpoint] = true;
newByOutpoint[outpoint] = fileInfo; newByOutpoint[outpoint] = fileInfo;
delete newLoading[uri];
return Object.assign({}, state, { return Object.assign({}, state, {
downloadingByOutpoint: newDownloading, downloadingByOutpoint: newDownloading,
urisLoading: newLoading,
byOutpoint: newByOutpoint, byOutpoint: newByOutpoint,
}); });
}; };
@ -91,7 +98,7 @@ reducers[ACTIONS.DOWNLOADING_PROGRESSED] = (state, action) => {
}; };
reducers[ACTIONS.DOWNLOADING_CANCELED] = (state, action) => { reducers[ACTIONS.DOWNLOADING_CANCELED] = (state, action) => {
const { outpoint } = action.data; const { uri, outpoint } = action.data;
const newDownloading = Object.assign({}, state.downloadingByOutpoint); const newDownloading = Object.assign({}, state.downloadingByOutpoint);
delete newDownloading[outpoint]; delete newDownloading[outpoint];
@ -131,36 +138,6 @@ reducers[ACTIONS.FILE_DELETE] = (state, action) => {
}); });
}; };
reducers[ACTIONS.LOADING_VIDEO_STARTED] = (state, action) => {
const { uri } = action.data;
const newLoading = Object.assign({}, state.urisLoading);
newLoading[uri] = true;
const newErrors = { ...state.errors };
if (uri in newErrors) delete newErrors[uri];
return Object.assign({}, state, {
urisLoading: newLoading,
errors: { ...newErrors },
});
};
reducers[ACTIONS.LOADING_VIDEO_FAILED] = (state, action) => {
const { uri } = action.data;
const newLoading = Object.assign({}, state.urisLoading);
delete newLoading[uri];
const newErrors = { ...state.errors };
newErrors[uri] = true;
return Object.assign({}, state, {
urisLoading: newLoading,
errors: { ...newErrors },
});
};
reducers[ACTIONS.SET_FILE_LIST_SORT] = (state, action) => { reducers[ACTIONS.SET_FILE_LIST_SORT] = (state, action) => {
const pageSortStates = { const pageSortStates = {
[PAGES.PUBLISHED]: 'fileListPublishedSort', [PAGES.PUBLISHED]: 'fileListPublishedSort',

View file

@ -1,5 +1,6 @@
// @flow // @flow
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { makeSelectFileInfoForUri } from 'redux/selectors/file_info';
type State = { file: FileState }; type State = { file: FileState };
@ -20,19 +21,16 @@ export const selectPurchasedUris: (state: State) => Array<string> = createSelect
state => state.purchasedUris state => state.purchasedUris
); );
export const selectPurchasedStreamingUrls: (state: State) => {} = createSelector(
selectState,
state => state.purchasedStreamingUrls
);
export const selectLastPurchasedUri: (state: State) => string = createSelector( export const selectLastPurchasedUri: (state: State) => string = createSelector(
selectState, selectState,
state => state =>
state.purchasedUris.length > 0 ? state.purchasedUris[state.purchasedUris.length - 1] : null state.purchasedUris.length > 0 ? state.purchasedUris[state.purchasedUris.length - 1] : null
); );
export const makeSelectStreamingUrlForUri = (uri: string): ((state: State) => {}) => export const makeSelectStreamingUrlForUri = (uri: string) =>
createSelector( createSelector(
selectPurchasedStreamingUrls, makeSelectFileInfoForUri(uri),
streamingUrls => streamingUrls && streamingUrls[uri] fileInfo => {
return fileInfo && fileInfo.streaming_url;
}
); );

View file

@ -3,9 +3,11 @@ import {
selectIsFetchingClaimListMine, selectIsFetchingClaimListMine,
selectMyClaims, selectMyClaims,
selectClaimsById, selectClaimsById,
makeSelectContentTypeForUri,
} from 'redux/selectors/claims'; } from 'redux/selectors/claims';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { buildURI } from 'lbryURI'; import { buildURI } from 'lbryURI';
import Lbry from 'lbry';
export const selectState = state => state.fileInfo || {}; export const selectState = state => state.fileInfo || {};
@ -72,7 +74,7 @@ export const selectFileInfosDownloaded = createSelector(
return ( return (
fileInfo && fileInfo &&
myClaimIds.indexOf(fileInfo.claim_id) === -1 && myClaimIds.indexOf(fileInfo.claim_id) === -1 &&
(fileInfo.completed || fileInfo.written_bytes) (fileInfo.completed || fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0)
); );
}) })
); );
@ -238,3 +240,41 @@ export const selectDownloadedUris = createSelector(
.reverse() .reverse()
.map(claim => `lbry://${claim.claim_name}#${claim.claim_id}`) .map(claim => `lbry://${claim.claim_name}#${claim.claim_id}`)
); );
export const makeSelectMediaTypeForUri = (uri: string) =>
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: string) =>
createSelector(
makeSelectMediaTypeForUri(uri),
mediaType => {
const isStreamable = ['audio', 'video', 'image'].indexOf(mediaType) !== -1;
return isStreamable;
}
);
export const makeSelectDownloadPathForUri = (uri: string) =>
createSelector(
makeSelectFileInfoForUri(uri),
fileInfo => {
return fileInfo && fileInfo.download_path;
}
);
export const makeSelectFileNameForUri = (uri: string) =>
createSelector(
makeSelectFileInfoForUri(uri),
fileInfo => {
return fileInfo && fileInfo.file_name;
}
);

View file

@ -3523,6 +3523,11 @@ mime-types@^2.1.12, mime-types@~2.1.17:
dependencies: dependencies:
mime-db "~1.33.0" mime-db "~1.33.0"
mime@^2.4.4:
version "2.4.4"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5"
integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==
mimic-fn@^1.0.0: mimic-fn@^1.0.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"