Range request support for desktop #176
348
dist/bundle.es.js
vendored
|
@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
||||
|
||||
require('proxy-polyfill');
|
||||
var mime = _interopDefault(require('mime'));
|
||||
var reselect = require('reselect');
|
||||
var uuid = _interopDefault(require('uuid/v4'));
|
||||
var fs = _interopDefault(require('fs'));
|
||||
|
@ -136,6 +137,7 @@ const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
|
|||
const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED';
|
||||
const FETCH_FILE_INFO_STARTED = 'FETCH_FILE_INFO_STARTED';
|
||||
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_COMPLETED = 'LOADING_VIDEO_COMPLETED';
|
||||
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_FAILED = 'PURCHASE_URI_FAILED';
|
||||
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
|
||||
const SEARCH_START = 'SEARCH_START';
|
||||
|
@ -365,6 +364,7 @@ var action_types = /*#__PURE__*/Object.freeze({
|
|||
FILE_LIST_SUCCEEDED: FILE_LIST_SUCCEEDED,
|
||||
FETCH_FILE_INFO_STARTED: FETCH_FILE_INFO_STARTED,
|
||||
FETCH_FILE_INFO_COMPLETED: FETCH_FILE_INFO_COMPLETED,
|
||||
FETCH_FILE_INFO_FAILED: FETCH_FILE_INFO_FAILED,
|
||||
LOADING_VIDEO_STARTED: LOADING_VIDEO_STARTED,
|
||||
LOADING_VIDEO_COMPLETED: LOADING_VIDEO_COMPLETED,
|
||||
LOADING_VIDEO_FAILED: LOADING_VIDEO_FAILED,
|
||||
|
@ -381,9 +381,6 @@ var action_types = /*#__PURE__*/Object.freeze({
|
|||
PURCHASE_URI_COMPLETED: PURCHASE_URI_COMPLETED,
|
||||
PURCHASE_URI_FAILED: PURCHASE_URI_FAILED,
|
||||
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_SUCCESS: SEARCH_SUCCESS,
|
||||
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
|
||||
getMediaType: (contentType, extname) => {
|
||||
if (extname) {
|
||||
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']];
|
||||
getMediaType: (contentType, fileName) => {
|
||||
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 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) => {
|
||||
switch (testpair[0].test(ret)) {
|
||||
case true:
|
||||
return testpair[1];
|
||||
default:
|
||||
return ret;
|
||||
const [regex, mediaType] = testpair;
|
||||
|
||||
return regex.test(ret) ? mediaType : ret;
|
||||
}, testString);
|
||||
|
||||
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';
|
||||
},
|
||||
|
||||
|
@ -2447,7 +2453,7 @@ const makeSelectLoadingForUri = uri => reselect.createSelector(selectUrisLoading
|
|||
const selectFileInfosDownloaded = reselect.createSelector(selectFileInfosByOutpoint, selectMyClaims, (byOutpoint, myClaims) => Object.values(byOutpoint).filter(fileInfo => {
|
||||
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) => {
|
||||
|
@ -2586,6 +2592,27 @@ const selectDownloadedUris = reselect.createSelector(selectFileInfosDownloaded,
|
|||
// 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}`));
|
||||
|
||||
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 || {};
|
||||
|
@ -2596,65 +2623,76 @@ const selectFailedPurchaseUris = reselect.createSelector(selectState$4, state =>
|
|||
|
||||
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 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) {
|
||||
return dispatch => {
|
||||
function doFileGet(uri, saveFile = true, onSuccess) {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const { nout, txid } = makeSelectClaimForUri(uri)(state);
|
||||
const outpoint = `${txid}:${nout}`;
|
||||
|
||||
dispatch({
|
||||
type: LOADING_FILE_STARTED,
|
||||
type: FETCH_FILE_INFO_STARTED,
|
||||
data: {
|
||||
uri
|
||||
outpoint
|
||||
}
|
||||
});
|
||||
|
||||
// set save_file argument to True to save the file (old behaviour)
|
||||
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) {
|
||||
dispatch({
|
||||
type: LOADING_FILE_FAILED,
|
||||
data: { uri }
|
||||
});
|
||||
dispatch({
|
||||
type: PURCHASE_URI_FAILED,
|
||||
data: { uri }
|
||||
type: FETCH_FILE_INFO_FAILED,
|
||||
data: { outpoint }
|
||||
});
|
||||
|
||||
dispatch(doToast({ message: `File timeout for uri ${uri}`, isError: true }));
|
||||
} else {
|
||||
// purchase was completed successfully
|
||||
const { streaming_url: streamingUrl } = streamInfo;
|
||||
dispatch({
|
||||
type: PURCHASE_URI_COMPLETED,
|
||||
data: { uri, streamingUrl: !saveFile && streamingUrl ? streamingUrl : null }
|
||||
});
|
||||
}
|
||||
}).catch(() => {
|
||||
dispatch({
|
||||
type: LOADING_FILE_FAILED,
|
||||
data: { uri }
|
||||
});
|
||||
dispatch({
|
||||
type: FETCH_FILE_INFO_COMPLETED,
|
||||
data: {
|
||||
fileInfo: streamInfo,
|
||||
outpoint: streamInfo.outpoint
|
||||
}
|
||||
});
|
||||
|
||||
if (onSuccess) {
|
||||
onSuccess(streamInfo);
|
||||
}
|
||||
}
|
||||
}).catch(() => {
|
||||
dispatch({
|
||||
type: PURCHASE_URI_FAILED,
|
||||
data: { uri }
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: FETCH_FILE_INFO_FAILED,
|
||||
data: { outpoint }
|
||||
});
|
||||
|
||||
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
|
||||
}));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function doPurchaseUri(uri, costInfo, saveFile = true) {
|
||||
function doPurchaseUri(uri, costInfo, saveFile = true, onSuccess) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: PURCHASE_URI_STARTED,
|
||||
|
@ -2685,7 +2723,7 @@ function doPurchaseUri(uri, costInfo, saveFile = true) {
|
|||
return;
|
||||
}
|
||||
|
||||
dispatch(doFileGet(uri, saveFile));
|
||||
dispatch(doFileGet(uri, saveFile, onSuccess));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -3831,8 +3869,6 @@ function contentReducer(state = defaultState$2, action) {
|
|||
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 defaultState$3 = {
|
||||
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) => {
|
||||
const { uri, outpoint, fileInfo } = action.data;
|
||||
|
||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||
const newDownloading = Object.assign({}, state.downloadingByOutpoint);
|
||||
const newLoading = Object.assign({}, state.urisLoading);
|
||||
|
||||
newDownloading[outpoint] = true;
|
||||
newByOutpoint[outpoint] = fileInfo;
|
||||
delete newLoading[uri];
|
||||
|
||||
return Object.assign({}, state, {
|
||||
downloadingByOutpoint: newDownloading,
|
||||
urisLoading: newLoading,
|
||||
byOutpoint: newByOutpoint
|
||||
});
|
||||
};
|
||||
|
@ -3921,7 +3964,7 @@ reducers$2[DOWNLOADING_PROGRESSED] = (state, action) => {
|
|||
};
|
||||
|
||||
reducers$2[DOWNLOADING_CANCELED] = (state, action) => {
|
||||
const { outpoint } = action.data;
|
||||
const { uri, outpoint } = action.data;
|
||||
|
||||
const newDownloading = Object.assign({}, state.downloadingByOutpoint);
|
||||
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) => {
|
||||
const pageSortStates = {
|
||||
[PUBLISHED]: 'fileListPublishedSort',
|
||||
|
@ -4010,13 +4023,12 @@ function fileInfoReducer(state = defaultState$3, action) {
|
|||
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 defaultState$4 = {
|
||||
failedPurchaseUris: [],
|
||||
purchasedUris: [],
|
||||
purchasedStreamingUrls: {},
|
||||
purchaseUriErrorMessage: ''
|
||||
};
|
||||
|
||||
|
@ -4027,17 +4039,16 @@ reducers$3[PURCHASE_URI_STARTED] = (state, action) => {
|
|||
newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1);
|
||||
}
|
||||
|
||||
return _extends$9({}, state, {
|
||||
return _extends$8({}, state, {
|
||||
failedPurchaseUris: newFailedPurchaseUris,
|
||||
purchaseUriErrorMessage: ''
|
||||
});
|
||||
};
|
||||
|
||||
reducers$3[PURCHASE_URI_COMPLETED] = (state, action) => {
|
||||
const { uri, streamingUrl } = action.data;
|
||||
const { uri } = action.data;
|
||||
const newPurchasedUris = state.purchasedUris.slice();
|
||||
const newFailedPurchaseUris = state.failedPurchaseUris.slice();
|
||||
const newPurchasedStreamingUrls = Object.assign({}, state.purchasedStreamingUrls);
|
||||
|
||||
if (!newPurchasedUris.includes(uri)) {
|
||||
newPurchasedUris.push(uri);
|
||||
|
@ -4045,14 +4056,10 @@ reducers$3[PURCHASE_URI_COMPLETED] = (state, action) => {
|
|||
if (newFailedPurchaseUris.includes(uri)) {
|
||||
newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1);
|
||||
}
|
||||
if (streamingUrl) {
|
||||
newPurchasedStreamingUrls[uri] = streamingUrl;
|
||||
}
|
||||
|
||||
return _extends$9({}, state, {
|
||||
return _extends$8({}, state, {
|
||||
failedPurchaseUris: newFailedPurchaseUris,
|
||||
purchasedUris: newPurchasedUris,
|
||||
purchasedStreamingUrls: newPurchasedStreamingUrls,
|
||||
purchaseUriErrorMessage: ''
|
||||
});
|
||||
};
|
||||
|
@ -4065,7 +4072,7 @@ reducers$3[PURCHASE_URI_FAILED] = (state, action) => {
|
|||
newFailedPurchaseUris.push(uri);
|
||||
}
|
||||
|
||||
return _extends$9({}, state, {
|
||||
return _extends$8({}, state, {
|
||||
failedPurchaseUris: newFailedPurchaseUris,
|
||||
purchaseUriErrorMessage: error
|
||||
});
|
||||
|
@ -4078,7 +4085,7 @@ reducers$3[DELETE_PURCHASED_URI] = (state, action) => {
|
|||
newPurchasedUris.splice(newPurchasedUris.indexOf(uri), 1);
|
||||
}
|
||||
|
||||
return _extends$9({}, state, {
|
||||
return _extends$8({}, state, {
|
||||
purchasedUris: newPurchasedUris
|
||||
});
|
||||
};
|
||||
|
@ -4089,7 +4096,7 @@ function fileReducer(state = defaultState$4, action) {
|
|||
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 = {
|
||||
notifications: [],
|
||||
|
@ -4104,7 +4111,7 @@ const notificationsReducer = handleActions({
|
|||
const newToasts = state.toasts.slice();
|
||||
newToasts.push(toast);
|
||||
|
||||
return _extends$a({}, state, {
|
||||
return _extends$9({}, state, {
|
||||
toasts: newToasts
|
||||
});
|
||||
},
|
||||
|
@ -4112,7 +4119,7 @@ const notificationsReducer = handleActions({
|
|||
const newToasts = state.toasts.slice();
|
||||
newToasts.shift();
|
||||
|
||||
return _extends$a({}, state, {
|
||||
return _extends$9({}, state, {
|
||||
toasts: newToasts
|
||||
});
|
||||
},
|
||||
|
@ -4123,7 +4130,7 @@ const notificationsReducer = handleActions({
|
|||
const newNotifications = state.notifications.slice();
|
||||
newNotifications.push(notification);
|
||||
|
||||
return _extends$a({}, state, {
|
||||
return _extends$9({}, state, {
|
||||
notifications: newNotifications
|
||||
});
|
||||
},
|
||||
|
@ -4134,7 +4141,7 @@ const notificationsReducer = handleActions({
|
|||
|
||||
notifications = notifications.map(pastNotification => pastNotification.id === notification.id ? notification : pastNotification);
|
||||
|
||||
return _extends$a({}, state, {
|
||||
return _extends$9({}, state, {
|
||||
notifications
|
||||
});
|
||||
},
|
||||
|
@ -4143,7 +4150,7 @@ const notificationsReducer = handleActions({
|
|||
let newNotifications = state.notifications.slice();
|
||||
newNotifications = newNotifications.filter(notification => notification.id !== id);
|
||||
|
||||
return _extends$a({}, state, {
|
||||
return _extends$9({}, state, {
|
||||
notifications: newNotifications
|
||||
});
|
||||
},
|
||||
|
@ -4154,7 +4161,7 @@ const notificationsReducer = handleActions({
|
|||
const newErrors = state.errors.slice();
|
||||
newErrors.push(error);
|
||||
|
||||
return _extends$a({}, state, {
|
||||
return _extends$9({}, state, {
|
||||
errors: newErrors
|
||||
});
|
||||
},
|
||||
|
@ -4162,13 +4169,13 @@ const notificationsReducer = handleActions({
|
|||
const newErrors = state.errors.slice();
|
||||
newErrors.shift();
|
||||
|
||||
return _extends$a({}, state, {
|
||||
return _extends$9({}, state, {
|
||||
errors: newErrors
|
||||
});
|
||||
}
|
||||
}, 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; }
|
||||
|
||||
|
@ -4205,17 +4212,17 @@ const defaultState$6 = {
|
|||
const publishReducer = handleActions({
|
||||
[UPDATE_PUBLISH_FORM]: (state, action) => {
|
||||
const { data } = action;
|
||||
return _extends$b({}, state, data);
|
||||
return _extends$a({}, state, data);
|
||||
},
|
||||
[CLEAR_PUBLISH]: () => _extends$b({}, defaultState$6),
|
||||
[PUBLISH_START]: state => _extends$b({}, state, {
|
||||
[CLEAR_PUBLISH]: () => _extends$a({}, defaultState$6),
|
||||
[PUBLISH_START]: state => _extends$a({}, state, {
|
||||
publishing: true,
|
||||
publishSuccess: false
|
||||
}),
|
||||
[PUBLISH_FAIL]: state => _extends$b({}, state, {
|
||||
[PUBLISH_FAIL]: state => _extends$a({}, state, {
|
||||
publishing: false
|
||||
}),
|
||||
[PUBLISH_SUCCESS]: state => _extends$b({}, state, {
|
||||
[PUBLISH_SUCCESS]: state => _extends$a({}, state, {
|
||||
publishing: false,
|
||||
publishSuccess: true
|
||||
}),
|
||||
|
@ -4230,14 +4237,14 @@ const publishReducer = handleActions({
|
|||
contentName: name
|
||||
});
|
||||
|
||||
return _extends$b({}, defaultState$6, publishData, {
|
||||
return _extends$a({}, defaultState$6, publishData, {
|
||||
editingURI: uri,
|
||||
uri: shortUri
|
||||
});
|
||||
}
|
||||
}, 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 = {
|
||||
isActive: false, // does the user have any typed text in the search input
|
||||
|
@ -4257,29 +4264,29 @@ const defaultState$7 = {
|
|||
};
|
||||
|
||||
const searchReducer = handleActions({
|
||||
[SEARCH_START]: state => _extends$c({}, state, {
|
||||
[SEARCH_START]: state => _extends$b({}, state, {
|
||||
searching: true
|
||||
}),
|
||||
[SEARCH_SUCCESS]: (state, action) => {
|
||||
const { query, uris } = action.data;
|
||||
|
||||
return _extends$c({}, state, {
|
||||
return _extends$b({}, state, {
|
||||
searching: false,
|
||||
urisByQuery: Object.assign({}, state.urisByQuery, { [query]: uris })
|
||||
});
|
||||
},
|
||||
|
||||
[SEARCH_FAIL]: state => _extends$c({}, state, {
|
||||
[SEARCH_FAIL]: state => _extends$b({}, state, {
|
||||
searching: false
|
||||
}),
|
||||
|
||||
[UPDATE_SEARCH_QUERY]: (state, action) => _extends$c({}, state, {
|
||||
[UPDATE_SEARCH_QUERY]: (state, action) => _extends$b({}, state, {
|
||||
searchQuery: action.data.query,
|
||||
isActive: true
|
||||
}),
|
||||
|
||||
[UPDATE_SEARCH_SUGGESTIONS]: (state, action) => _extends$c({}, state, {
|
||||
suggestions: _extends$c({}, state.suggestions, {
|
||||
[UPDATE_SEARCH_SUGGESTIONS]: (state, action) => _extends$b({}, state, {
|
||||
suggestions: _extends$b({}, state.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
|
||||
// user is on a file page. The search query will still be present on any
|
||||
// other page
|
||||
[DISMISS_NOTIFICATION]: state => _extends$c({}, state, {
|
||||
[DISMISS_NOTIFICATION]: state => _extends$b({}, state, {
|
||||
isActive: false
|
||||
}),
|
||||
|
||||
[SEARCH_FOCUS]: state => _extends$c({}, state, {
|
||||
[SEARCH_FOCUS]: state => _extends$b({}, state, {
|
||||
focused: true
|
||||
}),
|
||||
[SEARCH_BLUR]: state => _extends$c({}, state, {
|
||||
[SEARCH_BLUR]: state => _extends$b({}, state, {
|
||||
focused: false
|
||||
}),
|
||||
[UPDATE_SEARCH_OPTIONS]: (state, action) => {
|
||||
const { options: oldOptions } = state;
|
||||
const newOptions = action.data;
|
||||
const options = _extends$c({}, oldOptions, newOptions);
|
||||
return _extends$c({}, state, {
|
||||
const options = _extends$b({}, oldOptions, newOptions);
|
||||
return _extends$b({}, state, {
|
||||
options
|
||||
});
|
||||
}
|
||||
}, 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() {
|
||||
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 }
|
||||
}), {});
|
||||
}
|
||||
|
@ -4333,7 +4340,7 @@ const tagsReducer = handleActions({
|
|||
newFollowedTags.push(name);
|
||||
}
|
||||
|
||||
return _extends$d({}, state, {
|
||||
return _extends$c({}, state, {
|
||||
followedTags: newFollowedTags
|
||||
});
|
||||
},
|
||||
|
@ -4342,10 +4349,10 @@ const tagsReducer = handleActions({
|
|||
const { knownTags } = state;
|
||||
const { name } = action.data;
|
||||
|
||||
let newKnownTags = _extends$d({}, knownTags);
|
||||
let newKnownTags = _extends$c({}, knownTags);
|
||||
newKnownTags[name] = { name };
|
||||
|
||||
return _extends$d({}, state, {
|
||||
return _extends$c({}, state, {
|
||||
knownTags: newKnownTags
|
||||
});
|
||||
},
|
||||
|
@ -4354,11 +4361,11 @@ const tagsReducer = handleActions({
|
|||
const { knownTags, followedTags } = state;
|
||||
const { name } = action.data;
|
||||
|
||||
let newKnownTags = _extends$d({}, knownTags);
|
||||
let newKnownTags = _extends$c({}, knownTags);
|
||||
delete newKnownTags[name];
|
||||
const newFollowedTags = followedTags.filter(tag => tag !== name);
|
||||
|
||||
return _extends$d({}, state, {
|
||||
return _extends$c({}, state, {
|
||||
knownTags: newKnownTags,
|
||||
followedTags: newFollowedTags
|
||||
});
|
||||
|
@ -4389,7 +4396,7 @@ const blockedReducer = handleActions({
|
|||
}
|
||||
}, 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 = () => ({
|
||||
amount: undefined,
|
||||
|
@ -4429,25 +4436,25 @@ const defaultState$a = {
|
|||
};
|
||||
|
||||
const walletReducer = handleActions({
|
||||
[FETCH_TRANSACTIONS_STARTED]: state => _extends$e({}, state, {
|
||||
[FETCH_TRANSACTIONS_STARTED]: state => _extends$d({}, state, {
|
||||
fetchingTransactions: true
|
||||
}),
|
||||
|
||||
[FETCH_TRANSACTIONS_COMPLETED]: (state, action) => {
|
||||
const byId = _extends$e({}, state.transactions);
|
||||
const byId = _extends$d({}, state.transactions);
|
||||
|
||||
const { transactions } = action.data;
|
||||
transactions.forEach(transaction => {
|
||||
byId[transaction.txid] = transaction;
|
||||
});
|
||||
|
||||
return _extends$e({}, state, {
|
||||
return _extends$d({}, state, {
|
||||
transactions: byId,
|
||||
fetchingTransactions: false
|
||||
});
|
||||
},
|
||||
|
||||
[FETCH_SUPPORTS_STARTED]: state => _extends$e({}, state, {
|
||||
[FETCH_SUPPORTS_STARTED]: state => _extends$d({}, state, {
|
||||
fetchingSupports: true
|
||||
}),
|
||||
|
||||
|
@ -4460,7 +4467,7 @@ const walletReducer = handleActions({
|
|||
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) => {
|
||||
|
@ -4469,7 +4476,7 @@ const walletReducer = handleActions({
|
|||
|
||||
currentlyAbandoning[outpoint] = true;
|
||||
|
||||
return _extends$e({}, state, {
|
||||
return _extends$d({}, state, {
|
||||
abandoningSupportsByOutpoint: currentlyAbandoning
|
||||
});
|
||||
},
|
||||
|
@ -4482,56 +4489,56 @@ const walletReducer = handleActions({
|
|||
delete currentlyAbandoning[outpoint];
|
||||
delete byOutpoint[outpoint];
|
||||
|
||||
return _extends$e({}, state, {
|
||||
return _extends$d({}, state, {
|
||||
supports: byOutpoint,
|
||||
abandoningSupportsById: currentlyAbandoning
|
||||
});
|
||||
},
|
||||
|
||||
[GET_NEW_ADDRESS_STARTED]: state => _extends$e({}, state, {
|
||||
[GET_NEW_ADDRESS_STARTED]: state => _extends$d({}, state, {
|
||||
gettingNewAddress: true
|
||||
}),
|
||||
|
||||
[GET_NEW_ADDRESS_COMPLETED]: (state, action) => {
|
||||
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
|
||||
}),
|
||||
|
||||
[UPDATE_TOTAL_BALANCE]: (state, action) => _extends$e({}, state, {
|
||||
[UPDATE_TOTAL_BALANCE]: (state, action) => _extends$d({}, state, {
|
||||
totalBalance: action.data.totalBalance
|
||||
}),
|
||||
|
||||
[CHECK_ADDRESS_IS_MINE_STARTED]: state => _extends$e({}, state, {
|
||||
[CHECK_ADDRESS_IS_MINE_STARTED]: state => _extends$d({}, state, {
|
||||
checkingAddressOwnership: true
|
||||
}),
|
||||
|
||||
[CHECK_ADDRESS_IS_MINE_COMPLETED]: state => _extends$e({}, state, {
|
||||
[CHECK_ADDRESS_IS_MINE_COMPLETED]: state => _extends$d({}, state, {
|
||||
checkingAddressOwnership: false
|
||||
}),
|
||||
|
||||
[SET_DRAFT_TRANSACTION_AMOUNT]: (state, action) => {
|
||||
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) => {
|
||||
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 => {
|
||||
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, {
|
||||
|
@ -4544,103 +4551,103 @@ const walletReducer = handleActions({
|
|||
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
|
||||
}),
|
||||
|
||||
[SUPPORT_TRANSACTION_COMPLETED]: state => _extends$e({}, state, {
|
||||
[SUPPORT_TRANSACTION_COMPLETED]: state => _extends$d({}, state, {
|
||||
sendingSupport: false
|
||||
}),
|
||||
|
||||
[SUPPORT_TRANSACTION_FAILED]: (state, action) => _extends$e({}, state, {
|
||||
[SUPPORT_TRANSACTION_FAILED]: (state, action) => _extends$d({}, state, {
|
||||
error: action.data.error,
|
||||
sendingSupport: false
|
||||
}),
|
||||
|
||||
[WALLET_STATUS_COMPLETED]: (state, action) => _extends$e({}, state, {
|
||||
[WALLET_STATUS_COMPLETED]: (state, action) => _extends$d({}, state, {
|
||||
walletIsEncrypted: action.result
|
||||
}),
|
||||
|
||||
[WALLET_ENCRYPT_START]: state => _extends$e({}, state, {
|
||||
[WALLET_ENCRYPT_START]: state => _extends$d({}, state, {
|
||||
walletEncryptPending: true,
|
||||
walletEncryptSucceded: null,
|
||||
walletEncryptResult: null
|
||||
}),
|
||||
|
||||
[WALLET_ENCRYPT_COMPLETED]: (state, action) => _extends$e({}, state, {
|
||||
[WALLET_ENCRYPT_COMPLETED]: (state, action) => _extends$d({}, state, {
|
||||
walletEncryptPending: false,
|
||||
walletEncryptSucceded: true,
|
||||
walletEncryptResult: action.result
|
||||
}),
|
||||
|
||||
[WALLET_ENCRYPT_FAILED]: (state, action) => _extends$e({}, state, {
|
||||
[WALLET_ENCRYPT_FAILED]: (state, action) => _extends$d({}, state, {
|
||||
walletEncryptPending: false,
|
||||
walletEncryptSucceded: false,
|
||||
walletEncryptResult: action.result
|
||||
}),
|
||||
|
||||
[WALLET_DECRYPT_START]: state => _extends$e({}, state, {
|
||||
[WALLET_DECRYPT_START]: state => _extends$d({}, state, {
|
||||
walletDecryptPending: true,
|
||||
walletDecryptSucceded: null,
|
||||
walletDecryptResult: null
|
||||
}),
|
||||
|
||||
[WALLET_DECRYPT_COMPLETED]: (state, action) => _extends$e({}, state, {
|
||||
[WALLET_DECRYPT_COMPLETED]: (state, action) => _extends$d({}, state, {
|
||||
walletDecryptPending: false,
|
||||
walletDecryptSucceded: true,
|
||||
walletDecryptResult: action.result
|
||||
}),
|
||||
|
||||
[WALLET_DECRYPT_FAILED]: (state, action) => _extends$e({}, state, {
|
||||
[WALLET_DECRYPT_FAILED]: (state, action) => _extends$d({}, state, {
|
||||
walletDecryptPending: false,
|
||||
walletDecryptSucceded: false,
|
||||
walletDecryptResult: action.result
|
||||
}),
|
||||
|
||||
[WALLET_UNLOCK_START]: state => _extends$e({}, state, {
|
||||
[WALLET_UNLOCK_START]: state => _extends$d({}, state, {
|
||||
walletUnlockPending: true,
|
||||
walletUnlockSucceded: null,
|
||||
walletUnlockResult: null
|
||||
}),
|
||||
|
||||
[WALLET_UNLOCK_COMPLETED]: (state, action) => _extends$e({}, state, {
|
||||
[WALLET_UNLOCK_COMPLETED]: (state, action) => _extends$d({}, state, {
|
||||
walletUnlockPending: false,
|
||||
walletUnlockSucceded: true,
|
||||
walletUnlockResult: action.result
|
||||
}),
|
||||
|
||||
[WALLET_UNLOCK_FAILED]: (state, action) => _extends$e({}, state, {
|
||||
[WALLET_UNLOCK_FAILED]: (state, action) => _extends$d({}, state, {
|
||||
walletUnlockPending: false,
|
||||
walletUnlockSucceded: false,
|
||||
walletUnlockResult: action.result
|
||||
}),
|
||||
|
||||
[WALLET_LOCK_START]: state => _extends$e({}, state, {
|
||||
[WALLET_LOCK_START]: state => _extends$d({}, state, {
|
||||
walletLockPending: false,
|
||||
walletLockSucceded: null,
|
||||
walletLockResult: null
|
||||
}),
|
||||
|
||||
[WALLET_LOCK_COMPLETED]: (state, action) => _extends$e({}, state, {
|
||||
[WALLET_LOCK_COMPLETED]: (state, action) => _extends$d({}, state, {
|
||||
walletLockPending: false,
|
||||
walletLockSucceded: true,
|
||||
walletLockResult: action.result
|
||||
}),
|
||||
|
||||
[WALLET_LOCK_FAILED]: (state, action) => _extends$e({}, state, {
|
||||
[WALLET_LOCK_FAILED]: (state, action) => _extends$d({}, state, {
|
||||
walletLockPending: false,
|
||||
walletLockSucceded: false,
|
||||
walletLockResult: action.result
|
||||
}),
|
||||
|
||||
[SET_TRANSACTION_LIST_FILTER]: (state, action) => _extends$e({}, state, {
|
||||
[SET_TRANSACTION_LIST_FILTER]: (state, action) => _extends$d({}, state, {
|
||||
transactionListFilter: action.data
|
||||
}),
|
||||
|
||||
[UPDATE_CURRENT_HEIGHT]: (state, action) => _extends$e({}, state, {
|
||||
[UPDATE_CURRENT_HEIGHT]: (state, action) => _extends$d({}, state, {
|
||||
latestBlock: action.data
|
||||
})
|
||||
}, defaultState$a);
|
||||
|
@ -4656,14 +4663,14 @@ const makeSelectContentPositionForUri = uri => reselect.createSelector(selectSta
|
|||
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 selectToast = reselect.createSelector(selectState$7, state => {
|
||||
if (state.toasts.length) {
|
||||
const { id, params } = state.toasts[0];
|
||||
return _extends$f({
|
||||
return _extends$e({
|
||||
id
|
||||
}, params);
|
||||
}
|
||||
|
@ -4842,12 +4849,15 @@ exports.makeSelectContentPositionForUri = makeSelectContentPositionForUri;
|
|||
exports.makeSelectContentTypeForUri = makeSelectContentTypeForUri;
|
||||
exports.makeSelectCoverForUri = makeSelectCoverForUri;
|
||||
exports.makeSelectDateForUri = makeSelectDateForUri;
|
||||
exports.makeSelectDownloadPathForUri = makeSelectDownloadPathForUri;
|
||||
exports.makeSelectDownloadingForUri = makeSelectDownloadingForUri;
|
||||
exports.makeSelectFetchingChannelClaims = makeSelectFetchingChannelClaims;
|
||||
exports.makeSelectFileInfoForUri = makeSelectFileInfoForUri;
|
||||
exports.makeSelectFileNameForUri = makeSelectFileNameForUri;
|
||||
exports.makeSelectFirstRecommendedFileForUri = makeSelectFirstRecommendedFileForUri;
|
||||
exports.makeSelectIsUriResolving = makeSelectIsUriResolving;
|
||||
exports.makeSelectLoadingForUri = makeSelectLoadingForUri;
|
||||
exports.makeSelectMediaTypeForUri = makeSelectMediaTypeForUri;
|
||||
exports.makeSelectMetadataForUri = makeSelectMetadataForUri;
|
||||
exports.makeSelectMetadataItemForUri = makeSelectMetadataItemForUri;
|
||||
exports.makeSelectNsfwCountForChannel = makeSelectNsfwCountForChannel;
|
||||
|
@ -4864,6 +4874,7 @@ exports.makeSelectThumbnailForUri = makeSelectThumbnailForUri;
|
|||
exports.makeSelectTitleForUri = makeSelectTitleForUri;
|
||||
exports.makeSelectTotalItemsForChannel = makeSelectTotalItemsForChannel;
|
||||
exports.makeSelectTotalPagesForChannel = makeSelectTotalPagesForChannel;
|
||||
exports.makeSelectUriIsStreamable = makeSelectUriIsStreamable;
|
||||
exports.normalizeURI = normalizeURI;
|
||||
exports.notificationsReducer = notificationsReducer;
|
||||
exports.parseQueryParams = parseQueryParams;
|
||||
|
@ -4928,7 +4939,6 @@ exports.selectPendingClaims = selectPendingClaims;
|
|||
exports.selectPlayingUri = selectPlayingUri;
|
||||
exports.selectPublishFormValues = selectPublishFormValues;
|
||||
exports.selectPurchaseUriErrorMessage = selectPurchaseUriErrorMessage;
|
||||
exports.selectPurchasedStreamingUrls = selectPurchasedStreamingUrls;
|
||||
exports.selectPurchasedUris = selectPurchasedUris;
|
||||
exports.selectReceiveAddress = selectReceiveAddress;
|
||||
exports.selectRecentTransactions = selectRecentTransactions;
|
||||
|
|
5
dist/flow-typed/File.js
vendored
|
@ -38,7 +38,6 @@ declare type FileListItem = {
|
|||
declare type FileState = {
|
||||
failedPurchaseUris: Array<string>,
|
||||
purchasedUris: Array<string>,
|
||||
purchasedStreamingUrls: {},
|
||||
};
|
||||
|
||||
declare type PurchaseUriCompleted = {
|
||||
|
@ -53,7 +52,7 @@ declare type PurchaseUriFailed = {
|
|||
type: ACTIONS.PURCHASE_URI_FAILED,
|
||||
data: {
|
||||
uri: string,
|
||||
error: any
|
||||
error: any,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -68,6 +67,6 @@ declare type PurchaseUriStarted = {
|
|||
declare type DeletePurchasedUri = {
|
||||
type: ACTIONS.DELETE_PURCHASED_URI,
|
||||
data: {
|
||||
uri: string
|
||||
uri: string,
|
||||
},
|
||||
};
|
||||
|
|
2
dist/flow-typed/Lbry.js
vendored
|
@ -68,7 +68,7 @@ declare type ResolveResponse = {
|
|||
[string]: Claim | { error?: {} },
|
||||
};
|
||||
|
||||
declare type GetResponse = FileListItem;
|
||||
declare type GetResponse = FileListItem & { error?: string };
|
||||
|
||||
declare type GenericTxResponse = {
|
||||
height: number,
|
||||
|
|
4
dist/flow-typed/mime.js
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
// @flow
|
||||
declare module 'mime' {
|
||||
declare module.exports: any;
|
||||
}
|
5
flow-typed/File.js
vendored
|
@ -38,7 +38,6 @@ declare type FileListItem = {
|
|||
declare type FileState = {
|
||||
failedPurchaseUris: Array<string>,
|
||||
purchasedUris: Array<string>,
|
||||
purchasedStreamingUrls: {},
|
||||
};
|
||||
|
||||
declare type PurchaseUriCompleted = {
|
||||
|
@ -53,7 +52,7 @@ declare type PurchaseUriFailed = {
|
|||
type: ACTIONS.PURCHASE_URI_FAILED,
|
||||
data: {
|
||||
uri: string,
|
||||
error: any
|
||||
error: any,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -68,6 +67,6 @@ declare type PurchaseUriStarted = {
|
|||
declare type DeletePurchasedUri = {
|
||||
type: ACTIONS.DELETE_PURCHASED_URI,
|
||||
data: {
|
||||
uri: string
|
||||
uri: string,
|
||||
},
|
||||
};
|
||||
|
|
2
flow-typed/Lbry.js
vendored
|
@ -68,7 +68,7 @@ declare type ResolveResponse = {
|
|||
[string]: Claim | { error?: {} },
|
||||
};
|
||||
|
||||
declare type GetResponse = FileListItem;
|
||||
declare type GetResponse = FileListItem & { error?: string };
|
||||
|
||||
declare type GenericTxResponse = {
|
||||
height: number,
|
||||
|
|
4
flow-typed/mime.js
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
// @flow
|
||||
declare module 'mime' {
|
||||
declare module.exports: any;
|
||||
}
|
|
@ -28,6 +28,7 @@
|
|||
"format": "prettier 'src/**/*.{js,json}' --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"mime": "^2.4.4",
|
||||
"proxy-polyfill": "0.1.6",
|
||||
"reselect": "^3.0.0",
|
||||
"uuid": "^3.3.2"
|
||||
|
|
|
@ -111,6 +111,7 @@ export const FILE_LIST_STARTED = 'FILE_LIST_STARTED';
|
|||
export const FILE_LIST_SUCCEEDED = 'FILE_LIST_SUCCEEDED';
|
||||
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_FAILED = 'FETCH_FILE_INFO_FAILED';
|
||||
export const LOADING_VIDEO_STARTED = 'LOADING_VIDEO_STARTED';
|
||||
export const LOADING_VIDEO_COMPLETED = 'LOADING_VIDEO_COMPLETED';
|
||||
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_FAILED = 'PURCHASE_URI_FAILED';
|
||||
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
|
||||
export const SEARCH_START = 'SEARCH_START';
|
||||
|
|
|
@ -140,7 +140,6 @@ export { selectToast, selectError } from 'redux/selectors/notifications';
|
|||
export {
|
||||
selectFailedPurchaseUris,
|
||||
selectPurchasedUris,
|
||||
selectPurchasedStreamingUrls,
|
||||
selectPurchaseUriErrorMessage,
|
||||
selectLastPurchasedUri,
|
||||
makeSelectStreamingUrlForUri,
|
||||
|
@ -217,6 +216,10 @@ export {
|
|||
selectFileListDownloadedSort,
|
||||
selectFileListPublishedSort,
|
||||
selectDownloadedUris,
|
||||
makeSelectMediaTypeForUri,
|
||||
makeSelectUriIsStreamable,
|
||||
makeSelectDownloadPathForUri,
|
||||
makeSelectFileNameForUri,
|
||||
} from 'redux/selectors/file_info';
|
||||
|
||||
export {
|
||||
|
|
46
src/lbry.js
|
@ -1,5 +1,6 @@
|
|||
// @flow
|
||||
import 'proxy-polyfill';
|
||||
import mime from 'mime';
|
||||
|
||||
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
|
||||
getMediaType: (contentType: string, extname: ?string) => {
|
||||
if (extname) {
|
||||
getMediaType: (contentType?: string, fileName: ?string) => {
|
||||
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'],
|
||||
[/\.(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 extName = mime.getExtension(contentType);
|
||||
const fileExt = extName ? `.${extName}` : null;
|
||||
const testString = fileName || fileExt;
|
||||
|
||||
// Get mediaType from file extension
|
||||
I also mentioned to you that the SDK now returns a stream type:
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): 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) => {
|
||||
switch (testpair[0].test(ret)) {
|
||||
case true:
|
||||
return testpair[1];
|
||||
default:
|
||||
return ret;
|
||||
const [regex, mediaType] = testpair;
|
||||
|
||||
return regex.test(ret) ? mediaType : ret;
|
||||
}, testString);
|
||||
|
||||
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';
|
||||
},
|
||||
|
||||
|
|
|
@ -5,57 +5,70 @@ import { doToast } from 'redux/actions/notifications';
|
|||
import { selectBalance } from 'redux/selectors/wallet';
|
||||
import { makeSelectFileInfoForUri, selectDownloadingByOutpoint } from 'redux/selectors/file_info';
|
||||
import { makeSelectStreamingUrlForUri } from 'redux/selectors/file';
|
||||
import { makeSelectClaimForUri } from 'redux/selectors/claims';
|
||||
Since 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.
Ah that's a good point. I just searched for 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?
`GET_FILE_XXX` sounds perfect.
|
||||
|
||||
type Dispatch = (action: any) => any;
|
||||
type GetState = () => { file: FileState };
|
||||
|
||||
export function doFileGet(uri: string, saveFile: boolean = true) {
|
||||
return (dispatch: Dispatch) => {
|
||||
export function doFileGet(uri: string, saveFile: boolean = true, onSuccess?: GetResponse => any) {
|
||||
return (dispatch: Dispatch, getState: () => any) => {
|
||||
const state = getState();
|
||||
const { nout, txid } = makeSelectClaimForUri(uri)(state);
|
||||
const outpoint = `${txid}:${nout}`;
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.LOADING_FILE_STARTED,
|
||||
type: ACTIONS.FETCH_FILE_INFO_STARTED,
|
||||
data: {
|
||||
uri,
|
||||
outpoint,
|
||||
},
|
||||
});
|
||||
|
||||
// set save_file argument to True to save the file (old behaviour)
|
||||
Lbry.get({ uri, save_file: saveFile })
|
||||
.then((streamInfo: GetResponse) => {
|
||||
const timeout = streamInfo === null || typeof streamInfo !== 'object';
|
||||
const timeout =
|
||||
streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout';
|
||||
|
||||
if (timeout) {
|
||||
dispatch({
|
||||
type: ACTIONS.LOADING_FILE_FAILED,
|
||||
data: { uri },
|
||||
});
|
||||
dispatch({
|
||||
type: ACTIONS.PURCHASE_URI_FAILED,
|
||||
data: { uri },
|
||||
type: ACTIONS.FETCH_FILE_INFO_FAILED,
|
||||
data: { outpoint },
|
||||
});
|
||||
|
||||
dispatch(doToast({ message: `File timeout for uri ${uri}`, isError: true }));
|
||||
} else {
|
||||
// purchase was completed successfully
|
||||
const { streaming_url: streamingUrl } = streamInfo;
|
||||
dispatch({
|
||||
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(() => {
|
||||
dispatch({
|
||||
type: ACTIONS.LOADING_FILE_FAILED,
|
||||
data: { uri },
|
||||
});
|
||||
dispatch({
|
||||
type: ACTIONS.PURCHASE_URI_FAILED,
|
||||
data: { uri },
|
||||
});
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.FETCH_FILE_INFO_FAILED,
|
||||
data: { outpoint },
|
||||
});
|
||||
|
||||
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,
|
||||
})
|
||||
);
|
||||
|
@ -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) => {
|
||||
dispatch({
|
||||
type: ACTIONS.PURCHASE_URI_STARTED,
|
||||
|
@ -98,7 +116,7 @@ export function doPurchaseUri(uri: string, costInfo: { cost: number }, saveFile:
|
|||
return;
|
||||
}
|
||||
|
||||
dispatch(doFileGet(uri, saveFile));
|
||||
dispatch(doFileGet(uri, saveFile, onSuccess));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ const reducers = {};
|
|||
const defaultState = {
|
||||
failedPurchaseUris: [],
|
||||
purchasedUris: [],
|
||||
purchasedStreamingUrls: {},
|
||||
purchaseUriErrorMessage: '',
|
||||
};
|
||||
|
||||
|
@ -30,10 +29,9 @@ reducers[ACTIONS.PURCHASE_URI_COMPLETED] = (
|
|||
state: FileState,
|
||||
action: PurchaseUriCompleted
|
||||
): FileState => {
|
||||
const { uri, streamingUrl } = action.data;
|
||||
const { uri } = action.data;
|
||||
const newPurchasedUris = state.purchasedUris.slice();
|
||||
const newFailedPurchaseUris = state.failedPurchaseUris.slice();
|
||||
const newPurchasedStreamingUrls = Object.assign({}, state.purchasedStreamingUrls);
|
||||
|
||||
if (!newPurchasedUris.includes(uri)) {
|
||||
newPurchasedUris.push(uri);
|
||||
|
@ -41,15 +39,11 @@ reducers[ACTIONS.PURCHASE_URI_COMPLETED] = (
|
|||
if (newFailedPurchaseUris.includes(uri)) {
|
||||
newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1);
|
||||
}
|
||||
if (streamingUrl) {
|
||||
newPurchasedStreamingUrls[uri] = streamingUrl;
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
failedPurchaseUris: newFailedPurchaseUris,
|
||||
purchasedUris: newPurchasedUris,
|
||||
purchasedStreamingUrls: newPurchasedStreamingUrls,
|
||||
purchaseUriErrorMessage: '',
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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) => {
|
||||
const { uri, outpoint, fileInfo } = action.data;
|
||||
|
||||
const newByOutpoint = Object.assign({}, state.byOutpoint);
|
||||
const newDownloading = Object.assign({}, state.downloadingByOutpoint);
|
||||
const newLoading = Object.assign({}, state.urisLoading);
|
||||
|
||||
newDownloading[outpoint] = true;
|
||||
newByOutpoint[outpoint] = fileInfo;
|
||||
delete newLoading[uri];
|
||||
|
||||
return Object.assign({}, state, {
|
||||
downloadingByOutpoint: newDownloading,
|
||||
urisLoading: newLoading,
|
||||
byOutpoint: newByOutpoint,
|
||||
});
|
||||
};
|
||||
|
@ -91,7 +98,7 @@ reducers[ACTIONS.DOWNLOADING_PROGRESSED] = (state, action) => {
|
|||
};
|
||||
|
||||
reducers[ACTIONS.DOWNLOADING_CANCELED] = (state, action) => {
|
||||
const { outpoint } = action.data;
|
||||
const { uri, outpoint } = action.data;
|
||||
|
||||
const newDownloading = Object.assign({}, state.downloadingByOutpoint);
|
||||
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) => {
|
||||
const pageSortStates = {
|
||||
[PAGES.PUBLISHED]: 'fileListPublishedSort',
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// @flow
|
||||
import { createSelector } from 'reselect';
|
||||
import { makeSelectFileInfoForUri } from 'redux/selectors/file_info';
|
||||
|
||||
type State = { file: FileState };
|
||||
|
||||
|
@ -20,19 +21,16 @@ export const selectPurchasedUris: (state: State) => Array<string> = createSelect
|
|||
state => state.purchasedUris
|
||||
);
|
||||
|
||||
export const selectPurchasedStreamingUrls: (state: State) => {} = createSelector(
|
||||
selectState,
|
||||
state => state.purchasedStreamingUrls
|
||||
);
|
||||
|
||||
export const selectLastPurchasedUri: (state: State) => string = createSelector(
|
||||
selectState,
|
||||
state =>
|
||||
state.purchasedUris.length > 0 ? state.purchasedUris[state.purchasedUris.length - 1] : null
|
||||
);
|
||||
|
||||
export const makeSelectStreamingUrlForUri = (uri: string): ((state: State) => {}) =>
|
||||
export const makeSelectStreamingUrlForUri = (uri: string) =>
|
||||
createSelector(
|
||||
selectPurchasedStreamingUrls,
|
||||
streamingUrls => streamingUrls && streamingUrls[uri]
|
||||
makeSelectFileInfoForUri(uri),
|
||||
fileInfo => {
|
||||
return fileInfo && fileInfo.streaming_url;
|
||||
}
|
||||
);
|
||||
|
|
|
@ -3,9 +3,11 @@ import {
|
|||
selectIsFetchingClaimListMine,
|
||||
selectMyClaims,
|
||||
selectClaimsById,
|
||||
makeSelectContentTypeForUri,
|
||||
} from 'redux/selectors/claims';
|
||||
import { createSelector } from 'reselect';
|
||||
import { buildURI } from 'lbryURI';
|
||||
import Lbry from 'lbry';
|
||||
|
||||
export const selectState = state => state.fileInfo || {};
|
||||
|
||||
|
@ -72,7 +74,7 @@ export const selectFileInfosDownloaded = createSelector(
|
|||
return (
|
||||
fileInfo &&
|
||||
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()
|
||||
.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;
|
||||
}
|
||||
);
|
||||
|
|
|
@ -3523,6 +3523,11 @@ mime-types@^2.1.12, mime-types@~2.1.17:
|
|||
dependencies:
|
||||
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:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
|
||||
|
|
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.