Merge pull request #176 from lbryio/range-request

Range request support for desktop
This commit is contained in:
Sean Yesmunt 2019-08-13 13:33:58 -04:00 committed by GitHub
commit 05e70648e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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'));
@ -134,6 +135,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';
@ -150,9 +152,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';
@ -363,6 +362,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,
@ -379,9 +379,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,
@ -694,23 +691,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;
} else if (contentType) {
// $FlowFixMe
return (/^[^/]+/.exec(contentType)[0]
);
} }
// Get mediaType from contentType
if (contentType) {
const matches = /^[^/]+/.exec(contentType);
if (matches) {
return matches[0];
}
}
return 'unknown'; return 'unknown';
}, },
@ -2453,7 +2459,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) => {
@ -2592,6 +2598,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 || {};
@ -2602,65 +2629,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 } data: { uri }
}); });
dispatch({
type: FETCH_FILE_INFO_COMPLETED,
data: {
fileInfo: streamInfo,
outpoint: streamInfo.outpoint
}
});
if (onSuccess) {
onSuccess(streamInfo);
}
} }
}).catch(() => { }).catch(() => {
dispatch({
type: LOADING_FILE_FAILED,
data: { uri }
});
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,
@ -2691,7 +2729,7 @@ function doPurchaseUri(uri, costInfo, saveFile = true) {
return; return;
} }
dispatch(doFileGet(uri, saveFile)); dispatch(doFileGet(uri, saveFile, onSuccess));
}; };
} }
@ -3843,8 +3881,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,
@ -3899,20 +3935,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
}); });
}; };
@ -3933,7 +3976,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];
@ -3973,36 +4016,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',
@ -4022,13 +4035,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: ''
}; };
@ -4039,17 +4051,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);
@ -4057,14 +4068,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: ''
}); });
}; };
@ -4077,7 +4084,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
}); });
@ -4090,7 +4097,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
}); });
}; };
@ -4101,7 +4108,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: [],
@ -4116,7 +4123,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
}); });
}, },
@ -4124,7 +4131,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
}); });
}, },
@ -4135,7 +4142,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
}); });
}, },
@ -4146,7 +4153,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
}); });
}, },
@ -4155,7 +4162,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
}); });
}, },
@ -4166,7 +4173,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
}); });
}, },
@ -4174,13 +4181,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; }
@ -4217,17 +4224,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
}), }),
@ -4242,14 +4249,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
@ -4269,29 +4276,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
}) })
}), }),
@ -4299,30 +4306,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 }
}), {}); }), {});
} }
@ -4345,7 +4352,7 @@ const tagsReducer = handleActions({
newFollowedTags.push(name); newFollowedTags.push(name);
} }
return _extends$d({}, state, { return _extends$c({}, state, {
followedTags: newFollowedTags followedTags: newFollowedTags
}); });
}, },
@ -4354,10 +4361,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
}); });
}, },
@ -4366,11 +4373,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
}); });
@ -4401,7 +4408,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,
@ -4441,25 +4448,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
}), }),
@ -4472,7 +4479,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) => {
@ -4481,7 +4488,7 @@ const walletReducer = handleActions({
currentlyAbandoning[outpoint] = true; currentlyAbandoning[outpoint] = true;
return _extends$e({}, state, { return _extends$d({}, state, {
abandoningSupportsByOutpoint: currentlyAbandoning abandoningSupportsByOutpoint: currentlyAbandoning
}); });
}, },
@ -4494,56 +4501,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, {
@ -4556,103 +4563,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);
@ -4668,14 +4675,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);
} }
@ -4854,12 +4861,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;
@ -4876,6 +4886,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;
@ -4941,7 +4952,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,
@ -218,6 +217,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'], [/\.(h|go|ja|java|js|jsx|c|cpp|cs|css|rb|scss|sh|php|py)$/i, 'script'],
[/^(html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org)$/i, 'document'], [/\.(json|csv|txt|log|md|markdown|docx|pdf|xml|yml|yaml)$/i, 'document'],
[/^(stl|obj|fbx|gcode)$/i, '3D-file'], [/\.(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
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;
} else if (contentType) {
// $FlowFixMe
return /^[^/]+/.exec(contentType)[0];
} }
// Get mediaType from contentType
if (contentType) {
const matches = /^[^/]+/.exec(contentType);
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';
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"