refactor doPurchaseUri (#149)

This commit is contained in:
Akinwale Ariwodola 2019-05-21 20:18:07 +01:00 committed by GitHub
parent 29c7a4b832
commit 1fe1f6a188
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 542 additions and 101 deletions

382
dist/bundle.es.js vendored
View file

@ -116,6 +116,12 @@ const FETCH_AVAILABILITY_STARTED = 'FETCH_AVAILABILITY_STARTED';
const FETCH_AVAILABILITY_COMPLETED = 'FETCH_AVAILABILITY_COMPLETED'; const FETCH_AVAILABILITY_COMPLETED = 'FETCH_AVAILABILITY_COMPLETED';
const FILE_DELETE = 'FILE_DELETE'; const FILE_DELETE = 'FILE_DELETE';
const SET_FILE_LIST_SORT = 'SET_FILE_LIST_SORT'; const SET_FILE_LIST_SORT = 'SET_FILE_LIST_SORT';
const PURCHASE_URI_STARTED = 'PURCHASE_URI_STARTED';
const PURCHASE_URI_COMPLETED = 'PURCHASE_URI_COMPLETED';
const PURCHASE_URI_FAILED = 'PURCHASE_URI_FAILED';
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';
@ -228,6 +234,11 @@ const DISMISS_ERROR = 'DISMISS_ERROR';
const FETCH_DATE = 'FETCH_DATE'; const FETCH_DATE = 'FETCH_DATE';
// Cost info
const FETCH_COST_INFO_STARTED = 'FETCH_COST_INFO_STARTED';
const FETCH_COST_INFO_COMPLETED = 'FETCH_COST_INFO_COMPLETED';
const FETCH_COST_INFO_FAILED = 'FETCH_COST_INFO_FAILED';
var action_types = /*#__PURE__*/Object.freeze({ var action_types = /*#__PURE__*/Object.freeze({
WINDOW_FOCUSED: WINDOW_FOCUSED, WINDOW_FOCUSED: WINDOW_FOCUSED,
DAEMON_READY: DAEMON_READY, DAEMON_READY: DAEMON_READY,
@ -327,6 +338,12 @@ var action_types = /*#__PURE__*/Object.freeze({
FETCH_AVAILABILITY_COMPLETED: FETCH_AVAILABILITY_COMPLETED, FETCH_AVAILABILITY_COMPLETED: FETCH_AVAILABILITY_COMPLETED,
FILE_DELETE: FILE_DELETE, FILE_DELETE: FILE_DELETE,
SET_FILE_LIST_SORT: SET_FILE_LIST_SORT, SET_FILE_LIST_SORT: SET_FILE_LIST_SORT,
PURCHASE_URI_STARTED: PURCHASE_URI_STARTED,
PURCHASE_URI_COMPLETED: PURCHASE_URI_COMPLETED,
PURCHASE_URI_FAILED: PURCHASE_URI_FAILED,
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,
@ -418,7 +435,10 @@ var action_types = /*#__PURE__*/Object.freeze({
DISMISS_TOAST: DISMISS_TOAST, DISMISS_TOAST: DISMISS_TOAST,
CREATE_ERROR: CREATE_ERROR, CREATE_ERROR: CREATE_ERROR,
DISMISS_ERROR: DISMISS_ERROR, DISMISS_ERROR: DISMISS_ERROR,
FETCH_DATE: FETCH_DATE FETCH_DATE: FETCH_DATE,
FETCH_COST_INFO_STARTED: FETCH_COST_INFO_STARTED,
FETCH_COST_INFO_COMPLETED: FETCH_COST_INFO_COMPLETED,
FETCH_COST_INFO_FAILED: FETCH_COST_INFO_FAILED
}); });
const API_DOWN = 'apiDown'; const API_DOWN = 'apiDown';
@ -2295,6 +2315,108 @@ const selectFileListPublishedSort = reselect.createSelector(selectState$3, state
const selectFileListDownloadedSort = reselect.createSelector(selectState$3, state => state.fileListDownloadedSort); const selectFileListDownloadedSort = reselect.createSelector(selectState$3, state => state.fileListDownloadedSort);
//
const selectState$4 = state => state.file || {};
const selectFailedPurchaseUris = reselect.createSelector(selectState$4, state => state.failedPurchaseUris);
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]);
//
function doFileGet(uri, saveFile = true) {
return dispatch => {
dispatch({
type: LOADING_FILE_STARTED,
data: {
uri
}
});
// 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';
if (timeout) {
dispatch({
type: LOADING_FILE_FAILED,
data: { uri }
});
dispatch({
type: PURCHASE_URI_FAILED,
data: { uri }
});
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: PURCHASE_URI_FAILED,
data: { uri }
});
dispatch(doToast({
message: `Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.com/faq/support for support.`,
isError: true
}));
});
};
}
function doPurchaseUri(uri, costInfo, saveFile = true) {
return (dispatch, getState) => {
dispatch({
type: PURCHASE_URI_STARTED,
data: { uri }
});
const state = getState();
const balance = selectBalance(state);
const fileInfo = makeSelectFileInfoForUri(uri)(state);
const downloadingByOutpoint = selectDownloadingByOutpoint(state);
const alreadyDownloading = fileInfo && !!downloadingByOutpoint[fileInfo.outpoint];
const alreadyStreaming = makeSelectStreamingUrlForUri(uri)(state);
if (alreadyDownloading || alreadyStreaming) {
dispatch({
type: PURCHASE_URI_FAILED,
data: { uri, error: `Already fetching uri: ${uri}` }
});
return;
}
const { cost } = costInfo;
if (cost > balance) {
dispatch({
type: PURCHASE_URI_FAILED,
data: { uri, error: 'Insufficient credits' }
});
return;
}
dispatch(doFileGet(uri, saveFile));
};
}
function doFetchFileInfo(uri) { function doFetchFileInfo(uri) {
return (dispatch, getState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
@ -2790,15 +2912,65 @@ var _extends$4 = Object.assign || function (target) { for (var i = 1; i < argume
const reducers$1 = {}; const reducers$1 = {};
const defaultState$1 = { const defaultState$1 = {
failedPurchaseUris: [],
purchasedUris: [],
purchasedStreamingUrls: {}
};
reducers$1[PURCHASE_URI_COMPLETED] = (state, action) => {
const { uri, streamingUrl } = 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);
}
if (newFailedPurchaseUris.includes(uri)) {
newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1);
}
if (streamingUrl) {
newPurchasedStreamingUrls[uri] = streamingUrl;
}
return _extends$4({}, state, {
failedPurchaseUris: newFailedPurchaseUris,
purchasedUris: newPurchasedUris,
purchasedStreamingUrls: newPurchasedStreamingUrls
});
};
reducers$1[PURCHASE_URI_FAILED] = (state, action) => {
const { uri } = action.data;
const newFailedPurchaseUris = state.failedPurchaseUris.slice();
if (!newFailedPurchaseUris.includes(uri)) {
newFailedPurchaseUris.push(uri);
}
return _extends$4({}, state, {
failedPurchaseUris: newFailedPurchaseUris
});
};
function fileReducer(state = defaultState$1, action) {
const handler = reducers$1[action.type];
if (handler) return handler(state, action);
return state;
}
var _extends$5 = 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$2 = {
fileListPublishedSort: DATE_NEW, fileListPublishedSort: DATE_NEW,
fileListDownloadedSort: DATE_NEW fileListDownloadedSort: DATE_NEW
}; };
reducers$1[FILE_LIST_STARTED] = state => Object.assign({}, state, { reducers$2[FILE_LIST_STARTED] = state => Object.assign({}, state, {
isFetchingFileList: true isFetchingFileList: true
}); });
reducers$1[FILE_LIST_SUCCEEDED] = (state, action) => { reducers$2[FILE_LIST_SUCCEEDED] = (state, action) => {
const { fileInfos } = action.data; const { fileInfos } = action.data;
const newByOutpoint = Object.assign({}, state.byOutpoint); const newByOutpoint = Object.assign({}, state.byOutpoint);
const pendingByOutpoint = Object.assign({}, state.pendingByOutpoint); const pendingByOutpoint = Object.assign({}, state.pendingByOutpoint);
@ -2816,7 +2988,7 @@ reducers$1[FILE_LIST_SUCCEEDED] = (state, action) => {
}); });
}; };
reducers$1[FETCH_FILE_INFO_STARTED] = (state, action) => { reducers$2[FETCH_FILE_INFO_STARTED] = (state, action) => {
const { outpoint } = action.data; const { outpoint } = action.data;
const newFetching = Object.assign({}, state.fetching); const newFetching = Object.assign({}, state.fetching);
@ -2827,7 +2999,7 @@ reducers$1[FETCH_FILE_INFO_STARTED] = (state, action) => {
}); });
}; };
reducers$1[FETCH_FILE_INFO_COMPLETED] = (state, action) => { reducers$2[FETCH_FILE_INFO_COMPLETED] = (state, action) => {
const { fileInfo, outpoint } = action.data; const { fileInfo, outpoint } = action.data;
const newByOutpoint = Object.assign({}, state.byOutpoint); const newByOutpoint = Object.assign({}, state.byOutpoint);
@ -2842,7 +3014,7 @@ reducers$1[FETCH_FILE_INFO_COMPLETED] = (state, action) => {
}); });
}; };
reducers$1[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);
@ -2860,7 +3032,7 @@ reducers$1[DOWNLOADING_STARTED] = (state, action) => {
}); });
}; };
reducers$1[DOWNLOADING_PROGRESSED] = (state, action) => { reducers$2[DOWNLOADING_PROGRESSED] = (state, action) => {
const { outpoint, fileInfo } = action.data; const { outpoint, fileInfo } = action.data;
const newByOutpoint = Object.assign({}, state.byOutpoint); const newByOutpoint = Object.assign({}, state.byOutpoint);
@ -2875,7 +3047,7 @@ reducers$1[DOWNLOADING_PROGRESSED] = (state, action) => {
}); });
}; };
reducers$1[DOWNLOADING_CANCELED] = (state, action) => { reducers$2[DOWNLOADING_CANCELED] = (state, action) => {
const { outpoint } = action.data; const { outpoint } = action.data;
const newDownloading = Object.assign({}, state.downloadingByOutpoint); const newDownloading = Object.assign({}, state.downloadingByOutpoint);
@ -2886,7 +3058,7 @@ reducers$1[DOWNLOADING_CANCELED] = (state, action) => {
}); });
}; };
reducers$1[DOWNLOADING_COMPLETED] = (state, action) => { reducers$2[DOWNLOADING_COMPLETED] = (state, action) => {
const { outpoint, fileInfo } = action.data; const { outpoint, fileInfo } = action.data;
const newByOutpoint = Object.assign({}, state.byOutpoint); const newByOutpoint = Object.assign({}, state.byOutpoint);
@ -2901,7 +3073,7 @@ reducers$1[DOWNLOADING_COMPLETED] = (state, action) => {
}); });
}; };
reducers$1[FILE_DELETE] = (state, action) => { reducers$2[FILE_DELETE] = (state, action) => {
const { outpoint } = action.data; const { outpoint } = action.data;
const newByOutpoint = Object.assign({}, state.byOutpoint); const newByOutpoint = Object.assign({}, state.byOutpoint);
@ -2916,37 +3088,37 @@ reducers$1[FILE_DELETE] = (state, action) => {
}); });
}; };
reducers$1[LOADING_VIDEO_STARTED] = (state, action) => { reducers$2[LOADING_VIDEO_STARTED] = (state, action) => {
const { uri } = action.data; const { uri } = action.data;
const newLoading = Object.assign({}, state.urisLoading); const newLoading = Object.assign({}, state.urisLoading);
newLoading[uri] = true; newLoading[uri] = true;
const newErrors = _extends$4({}, state.errors); const newErrors = _extends$5({}, state.errors);
if (uri in newErrors) delete newErrors[uri]; if (uri in newErrors) delete newErrors[uri];
return Object.assign({}, state, { return Object.assign({}, state, {
urisLoading: newLoading, urisLoading: newLoading,
errors: _extends$4({}, newErrors) errors: _extends$5({}, newErrors)
}); });
}; };
reducers$1[LOADING_VIDEO_FAILED] = (state, action) => { reducers$2[LOADING_VIDEO_FAILED] = (state, action) => {
const { uri } = action.data; const { uri } = action.data;
const newLoading = Object.assign({}, state.urisLoading); const newLoading = Object.assign({}, state.urisLoading);
delete newLoading[uri]; delete newLoading[uri];
const newErrors = _extends$4({}, state.errors); const newErrors = _extends$5({}, state.errors);
newErrors[uri] = true; newErrors[uri] = true;
return Object.assign({}, state, { return Object.assign({}, state, {
urisLoading: newLoading, urisLoading: newLoading,
errors: _extends$4({}, newErrors) errors: _extends$5({}, newErrors)
}); });
}; };
reducers$1[FETCH_DATE] = (state, action) => { reducers$2[FETCH_DATE] = (state, action) => {
const { time } = action.data; const { time } = action.data;
if (time) { if (time) {
return Object.assign({}, state, { return Object.assign({}, state, {
@ -2956,7 +3128,7 @@ reducers$1[FETCH_DATE] = (state, action) => {
return null; return null;
}; };
reducers$1[SET_FILE_LIST_SORT] = (state, action) => { reducers$2[SET_FILE_LIST_SORT] = (state, action) => {
const pageSortStates = { const pageSortStates = {
[PUBLISHED]: 'fileListPublishedSort', [PUBLISHED]: 'fileListPublishedSort',
[DOWNLOADED]: 'fileListDownloadedSort' [DOWNLOADED]: 'fileListDownloadedSort'
@ -2969,8 +3141,8 @@ reducers$1[SET_FILE_LIST_SORT] = (state, action) => {
}); });
}; };
function fileInfoReducer(state = defaultState$1, action) { function fileInfoReducer(state = defaultState$2, action) {
const handler = reducers$1[action.type]; const handler = reducers$2[action.type];
if (handler) return handler(state, action); if (handler) return handler(state, action);
return state; return state;
} }
@ -2993,9 +3165,9 @@ const handleActions = (actionMap, defaultState) => (state = defaultState, action
return state; return state;
}; };
var _extends$5 = 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$6 = 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$2 = { const defaultState$3 = {
notifications: [], notifications: [],
toasts: [], toasts: [],
errors: [] errors: []
@ -3008,7 +3180,7 @@ const notificationsReducer = handleActions({
const newToasts = state.toasts.slice(); const newToasts = state.toasts.slice();
newToasts.push(toast); newToasts.push(toast);
return _extends$5({}, state, { return _extends$6({}, state, {
toasts: newToasts toasts: newToasts
}); });
}, },
@ -3016,7 +3188,7 @@ const notificationsReducer = handleActions({
const newToasts = state.toasts.slice(); const newToasts = state.toasts.slice();
newToasts.shift(); newToasts.shift();
return _extends$5({}, state, { return _extends$6({}, state, {
toasts: newToasts toasts: newToasts
}); });
}, },
@ -3027,7 +3199,7 @@ const notificationsReducer = handleActions({
const newNotifications = state.notifications.slice(); const newNotifications = state.notifications.slice();
newNotifications.push(notification); newNotifications.push(notification);
return _extends$5({}, state, { return _extends$6({}, state, {
notifications: newNotifications notifications: newNotifications
}); });
}, },
@ -3038,7 +3210,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$5({}, state, { return _extends$6({}, state, {
notifications notifications
}); });
}, },
@ -3047,7 +3219,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$5({}, state, { return _extends$6({}, state, {
notifications: newNotifications notifications: newNotifications
}); });
}, },
@ -3058,7 +3230,7 @@ const notificationsReducer = handleActions({
const newErrors = state.errors.slice(); const newErrors = state.errors.slice();
newErrors.push(error); newErrors.push(error);
return _extends$5({}, state, { return _extends$6({}, state, {
errors: newErrors errors: newErrors
}); });
}, },
@ -3066,15 +3238,15 @@ const notificationsReducer = handleActions({
const newErrors = state.errors.slice(); const newErrors = state.errors.slice();
newErrors.shift(); newErrors.shift();
return _extends$5({}, state, { return _extends$6({}, state, {
errors: newErrors errors: newErrors
}); });
} }
}, defaultState$2); }, defaultState$3);
var _extends$6 = 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$7 = 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$3 = { const defaultState$4 = {
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
focused: false, // is the search input focused focused: false, // is the search input focused
searchQuery: '', // needs to be an empty string for input focusing searchQuery: '', // needs to be an empty string for input focusing
@ -3092,29 +3264,29 @@ const defaultState$3 = {
}; };
const searchReducer = handleActions({ const searchReducer = handleActions({
[SEARCH_START]: state => _extends$6({}, state, { [SEARCH_START]: state => _extends$7({}, 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$6({}, state, { return _extends$7({}, state, {
searching: false, searching: false,
urisByQuery: Object.assign({}, state.urisByQuery, { [query]: uris }) urisByQuery: Object.assign({}, state.urisByQuery, { [query]: uris })
}); });
}, },
[SEARCH_FAIL]: state => _extends$6({}, state, { [SEARCH_FAIL]: state => _extends$7({}, state, {
searching: false searching: false
}), }),
[UPDATE_SEARCH_QUERY]: (state, action) => _extends$6({}, state, { [UPDATE_SEARCH_QUERY]: (state, action) => _extends$7({}, state, {
searchQuery: action.data.query, searchQuery: action.data.query,
isActive: true isActive: true
}), }),
[UPDATE_SEARCH_SUGGESTIONS]: (state, action) => _extends$6({}, state, { [UPDATE_SEARCH_SUGGESTIONS]: (state, action) => _extends$7({}, state, {
suggestions: _extends$6({}, state.suggestions, { suggestions: _extends$7({}, state.suggestions, {
[action.data.query]: action.data.suggestions [action.data.query]: action.data.suggestions
}) })
}), }),
@ -3122,27 +3294,27 @@ 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$6({}, state, { [DISMISS_NOTIFICATION]: state => _extends$7({}, state, {
isActive: false isActive: false
}), }),
[SEARCH_FOCUS]: state => _extends$6({}, state, { [SEARCH_FOCUS]: state => _extends$7({}, state, {
focused: true focused: true
}), }),
[SEARCH_BLUR]: state => _extends$6({}, state, { [SEARCH_BLUR]: state => _extends$7({}, 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$6({}, oldOptions, newOptions); const options = _extends$7({}, oldOptions, newOptions);
return _extends$6({}, state, { return _extends$7({}, state, {
options options
}); });
} }
}, defaultState$3); }, defaultState$4);
var _extends$7 = 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 buildDraftTransaction = () => ({ const buildDraftTransaction = () => ({
amount: undefined, amount: undefined,
@ -3153,7 +3325,7 @@ const buildDraftTransaction = () => ({
// See details in https://github.com/lbryio/lbry/issues/1307 // See details in https://github.com/lbryio/lbry/issues/1307
const defaultState$4 = { const defaultState$5 = {
balance: undefined, balance: undefined,
totalBalance: undefined, totalBalance: undefined,
latestBlock: undefined, latestBlock: undefined,
@ -3182,25 +3354,25 @@ const defaultState$4 = {
}; };
const walletReducer = handleActions({ const walletReducer = handleActions({
[FETCH_TRANSACTIONS_STARTED]: state => _extends$7({}, state, { [FETCH_TRANSACTIONS_STARTED]: state => _extends$8({}, state, {
fetchingTransactions: true fetchingTransactions: true
}), }),
[FETCH_TRANSACTIONS_COMPLETED]: (state, action) => { [FETCH_TRANSACTIONS_COMPLETED]: (state, action) => {
const byId = _extends$7({}, state.transactions); const byId = _extends$8({}, 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$7({}, state, { return _extends$8({}, state, {
transactions: byId, transactions: byId,
fetchingTransactions: false fetchingTransactions: false
}); });
}, },
[FETCH_SUPPORTS_STARTED]: state => _extends$7({}, state, { [FETCH_SUPPORTS_STARTED]: state => _extends$8({}, state, {
fetchingSupports: true fetchingSupports: true
}), }),
@ -3213,7 +3385,7 @@ const walletReducer = handleActions({
byOutpoint[`${txid}:${nout}`] = transaction; byOutpoint[`${txid}:${nout}`] = transaction;
}); });
return _extends$7({}, state, { supports: byOutpoint, fetchingSupports: false }); return _extends$8({}, state, { supports: byOutpoint, fetchingSupports: false });
}, },
[ABANDON_SUPPORT_STARTED]: (state, action) => { [ABANDON_SUPPORT_STARTED]: (state, action) => {
@ -3222,7 +3394,7 @@ const walletReducer = handleActions({
currentlyAbandoning[outpoint] = true; currentlyAbandoning[outpoint] = true;
return _extends$7({}, state, { return _extends$8({}, state, {
abandoningSupportsByOutpoint: currentlyAbandoning abandoningSupportsByOutpoint: currentlyAbandoning
}); });
}, },
@ -3235,56 +3407,56 @@ const walletReducer = handleActions({
delete currentlyAbandoning[outpoint]; delete currentlyAbandoning[outpoint];
delete byOutpoint[outpoint]; delete byOutpoint[outpoint];
return _extends$7({}, state, { return _extends$8({}, state, {
supports: byOutpoint, supports: byOutpoint,
abandoningSupportsById: currentlyAbandoning abandoningSupportsById: currentlyAbandoning
}); });
}, },
[GET_NEW_ADDRESS_STARTED]: state => _extends$7({}, state, { [GET_NEW_ADDRESS_STARTED]: state => _extends$8({}, 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$7({}, state, { gettingNewAddress: false, receiveAddress: address }); return _extends$8({}, state, { gettingNewAddress: false, receiveAddress: address });
}, },
[UPDATE_BALANCE]: (state, action) => _extends$7({}, state, { [UPDATE_BALANCE]: (state, action) => _extends$8({}, state, {
balance: action.data.balance balance: action.data.balance
}), }),
[UPDATE_TOTAL_BALANCE]: (state, action) => _extends$7({}, state, { [UPDATE_TOTAL_BALANCE]: (state, action) => _extends$8({}, state, {
totalBalance: action.data.totalBalance totalBalance: action.data.totalBalance
}), }),
[CHECK_ADDRESS_IS_MINE_STARTED]: state => _extends$7({}, state, { [CHECK_ADDRESS_IS_MINE_STARTED]: state => _extends$8({}, state, {
checkingAddressOwnership: true checkingAddressOwnership: true
}), }),
[CHECK_ADDRESS_IS_MINE_COMPLETED]: state => _extends$7({}, state, { [CHECK_ADDRESS_IS_MINE_COMPLETED]: state => _extends$8({}, 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$7({}, oldDraft, { amount: parseFloat(action.data.amount) }); const newDraft = _extends$8({}, oldDraft, { amount: parseFloat(action.data.amount) });
return _extends$7({}, state, { draftTransaction: newDraft }); return _extends$8({}, 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$7({}, oldDraft, { address: action.data.address }); const newDraft = _extends$8({}, oldDraft, { address: action.data.address });
return _extends$7({}, state, { draftTransaction: newDraft }); return _extends$8({}, state, { draftTransaction: newDraft });
}, },
[SEND_TRANSACTION_STARTED]: state => { [SEND_TRANSACTION_STARTED]: state => {
const newDraftTransaction = _extends$7({}, state.draftTransaction, { sending: true }); const newDraftTransaction = _extends$8({}, state.draftTransaction, { sending: true });
return _extends$7({}, state, { draftTransaction: newDraftTransaction }); return _extends$8({}, state, { draftTransaction: newDraftTransaction });
}, },
[SEND_TRANSACTION_COMPLETED]: state => Object.assign({}, state, { [SEND_TRANSACTION_COMPLETED]: state => Object.assign({}, state, {
@ -3297,134 +3469,134 @@ const walletReducer = handleActions({
error: action.data.error error: action.data.error
}); });
return _extends$7({}, state, { draftTransaction: newDraftTransaction }); return _extends$8({}, state, { draftTransaction: newDraftTransaction });
}, },
[SUPPORT_TRANSACTION_STARTED]: state => _extends$7({}, state, { [SUPPORT_TRANSACTION_STARTED]: state => _extends$8({}, state, {
sendingSupport: true sendingSupport: true
}), }),
[SUPPORT_TRANSACTION_COMPLETED]: state => _extends$7({}, state, { [SUPPORT_TRANSACTION_COMPLETED]: state => _extends$8({}, state, {
sendingSupport: false sendingSupport: false
}), }),
[SUPPORT_TRANSACTION_FAILED]: (state, action) => _extends$7({}, state, { [SUPPORT_TRANSACTION_FAILED]: (state, action) => _extends$8({}, state, {
error: action.data.error, error: action.data.error,
sendingSupport: false sendingSupport: false
}), }),
[WALLET_STATUS_COMPLETED]: (state, action) => _extends$7({}, state, { [WALLET_STATUS_COMPLETED]: (state, action) => _extends$8({}, state, {
walletIsEncrypted: action.result walletIsEncrypted: action.result
}), }),
[WALLET_ENCRYPT_START]: state => _extends$7({}, state, { [WALLET_ENCRYPT_START]: state => _extends$8({}, state, {
walletEncryptPending: true, walletEncryptPending: true,
walletEncryptSucceded: null, walletEncryptSucceded: null,
walletEncryptResult: null walletEncryptResult: null
}), }),
[WALLET_ENCRYPT_COMPLETED]: (state, action) => _extends$7({}, state, { [WALLET_ENCRYPT_COMPLETED]: (state, action) => _extends$8({}, state, {
walletEncryptPending: false, walletEncryptPending: false,
walletEncryptSucceded: true, walletEncryptSucceded: true,
walletEncryptResult: action.result walletEncryptResult: action.result
}), }),
[WALLET_ENCRYPT_FAILED]: (state, action) => _extends$7({}, state, { [WALLET_ENCRYPT_FAILED]: (state, action) => _extends$8({}, state, {
walletEncryptPending: false, walletEncryptPending: false,
walletEncryptSucceded: false, walletEncryptSucceded: false,
walletEncryptResult: action.result walletEncryptResult: action.result
}), }),
[WALLET_DECRYPT_START]: state => _extends$7({}, state, { [WALLET_DECRYPT_START]: state => _extends$8({}, state, {
walletDecryptPending: true, walletDecryptPending: true,
walletDecryptSucceded: null, walletDecryptSucceded: null,
walletDecryptResult: null walletDecryptResult: null
}), }),
[WALLET_DECRYPT_COMPLETED]: (state, action) => _extends$7({}, state, { [WALLET_DECRYPT_COMPLETED]: (state, action) => _extends$8({}, state, {
walletDecryptPending: false, walletDecryptPending: false,
walletDecryptSucceded: true, walletDecryptSucceded: true,
walletDecryptResult: action.result walletDecryptResult: action.result
}), }),
[WALLET_DECRYPT_FAILED]: (state, action) => _extends$7({}, state, { [WALLET_DECRYPT_FAILED]: (state, action) => _extends$8({}, state, {
walletDecryptPending: false, walletDecryptPending: false,
walletDecryptSucceded: false, walletDecryptSucceded: false,
walletDecryptResult: action.result walletDecryptResult: action.result
}), }),
[WALLET_UNLOCK_START]: state => _extends$7({}, state, { [WALLET_UNLOCK_START]: state => _extends$8({}, state, {
walletUnlockPending: true, walletUnlockPending: true,
walletUnlockSucceded: null, walletUnlockSucceded: null,
walletUnlockResult: null walletUnlockResult: null
}), }),
[WALLET_UNLOCK_COMPLETED]: (state, action) => _extends$7({}, state, { [WALLET_UNLOCK_COMPLETED]: (state, action) => _extends$8({}, state, {
walletUnlockPending: false, walletUnlockPending: false,
walletUnlockSucceded: true, walletUnlockSucceded: true,
walletUnlockResult: action.result walletUnlockResult: action.result
}), }),
[WALLET_UNLOCK_FAILED]: (state, action) => _extends$7({}, state, { [WALLET_UNLOCK_FAILED]: (state, action) => _extends$8({}, state, {
walletUnlockPending: false, walletUnlockPending: false,
walletUnlockSucceded: false, walletUnlockSucceded: false,
walletUnlockResult: action.result walletUnlockResult: action.result
}), }),
[WALLET_LOCK_START]: state => _extends$7({}, state, { [WALLET_LOCK_START]: state => _extends$8({}, state, {
walletLockPending: false, walletLockPending: false,
walletLockSucceded: null, walletLockSucceded: null,
walletLockResult: null walletLockResult: null
}), }),
[WALLET_LOCK_COMPLETED]: (state, action) => _extends$7({}, state, { [WALLET_LOCK_COMPLETED]: (state, action) => _extends$8({}, state, {
walletLockPending: false, walletLockPending: false,
walletLockSucceded: true, walletLockSucceded: true,
walletLockResult: action.result walletLockResult: action.result
}), }),
[WALLET_LOCK_FAILED]: (state, action) => _extends$7({}, state, { [WALLET_LOCK_FAILED]: (state, action) => _extends$8({}, state, {
walletLockPending: false, walletLockPending: false,
walletLockSucceded: false, walletLockSucceded: false,
walletLockResult: action.result walletLockResult: action.result
}), }),
[SET_TRANSACTION_LIST_FILTER]: (state, action) => _extends$7({}, state, { [SET_TRANSACTION_LIST_FILTER]: (state, action) => _extends$8({}, state, {
transactionListFilter: action.data transactionListFilter: action.data
}), }),
[UPDATE_CURRENT_HEIGHT]: (state, action) => _extends$7({}, state, { [UPDATE_CURRENT_HEIGHT]: (state, action) => _extends$8({}, state, {
latestBlock: action.data latestBlock: action.data
}) })
}, defaultState$4); }, defaultState$5);
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; }; 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 reducers$2 = {}; const reducers$3 = {};
const defaultState$5 = { const defaultState$6 = {
positions: {} positions: {}
}; };
reducers$2[SET_CONTENT_POSITION] = (state, action) => { reducers$3[SET_CONTENT_POSITION] = (state, action) => {
const { claimId, outpoint, position } = action.data; const { claimId, outpoint, position } = action.data;
return _extends$8({}, state, { return _extends$9({}, state, {
positions: _extends$8({}, state.positions, { positions: _extends$9({}, state.positions, {
[claimId]: _extends$8({}, state.positions[claimId], { [claimId]: _extends$9({}, state.positions[claimId], {
[outpoint]: position [outpoint]: position
}) })
}) })
}); });
}; };
function contentReducer(state = defaultState$5, action) { function contentReducer(state = defaultState$6, action) {
const handler = reducers$2[action.type]; const handler = reducers$3[action.type];
if (handler) return handler(state, action); if (handler) return handler(state, action);
return state; return state;
} }
const selectState$4 = state => state.content || {}; const selectState$5 = state => state.content || {};
const makeSelectContentPositionForUri = uri => reselect.createSelector(selectState$4, makeSelectClaimForUri(uri), (state, claim) => { const makeSelectContentPositionForUri = uri => reselect.createSelector(selectState$5, makeSelectClaimForUri(uri), (state, claim) => {
if (!claim) { if (!claim) {
return null; return null;
} }
@ -3433,14 +3605,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$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$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; };
const selectState$5 = state => state.notifications || {}; const selectState$6 = state => state.notifications || {};
const selectToast = reselect.createSelector(selectState$5, state => { const selectToast = reselect.createSelector(selectState$6, state => {
if (state.toasts.length) { if (state.toasts.length) {
const { id, params } = state.toasts[0]; const { id, params } = state.toasts[0];
return _extends$9({ return _extends$a({
id id
}, params); }, params);
} }
@ -3448,7 +3620,7 @@ const selectToast = reselect.createSelector(selectState$5, state => {
return null; return null;
}); });
const selectError = reselect.createSelector(selectState$5, state => { const selectError = reselect.createSelector(selectState$6, state => {
if (state.errors.length) { if (state.errors.length) {
const { error } = state.errors[0]; const { error } = state.errors[0];
return { return {
@ -3488,9 +3660,11 @@ exports.doFetchClaimsByChannel = doFetchClaimsByChannel;
exports.doFetchFileInfo = doFetchFileInfo; exports.doFetchFileInfo = doFetchFileInfo;
exports.doFetchFileInfosAndPublishedClaims = doFetchFileInfosAndPublishedClaims; exports.doFetchFileInfosAndPublishedClaims = doFetchFileInfosAndPublishedClaims;
exports.doFetchTransactions = doFetchTransactions; exports.doFetchTransactions = doFetchTransactions;
exports.doFileGet = doFileGet;
exports.doFileList = doFileList; exports.doFileList = doFileList;
exports.doFocusSearchInput = doFocusSearchInput; exports.doFocusSearchInput = doFocusSearchInput;
exports.doGetNewAddress = doGetNewAddress; exports.doGetNewAddress = doGetNewAddress;
exports.doPurchaseUri = doPurchaseUri;
exports.doResolveUri = doResolveUri; exports.doResolveUri = doResolveUri;
exports.doResolveUris = doResolveUris; exports.doResolveUris = doResolveUris;
exports.doSearch = doSearch; exports.doSearch = doSearch;
@ -3512,6 +3686,7 @@ exports.doWalletEncrypt = doWalletEncrypt;
exports.doWalletStatus = doWalletStatus; exports.doWalletStatus = doWalletStatus;
exports.doWalletUnlock = doWalletUnlock; exports.doWalletUnlock = doWalletUnlock;
exports.fileInfoReducer = fileInfoReducer; exports.fileInfoReducer = fileInfoReducer;
exports.fileReducer = fileReducer;
exports.formatCredits = formatCredits; exports.formatCredits = formatCredits;
exports.formatFullPrice = formatFullPrice; exports.formatFullPrice = formatFullPrice;
exports.isClaimNsfw = isClaimNsfw; exports.isClaimNsfw = isClaimNsfw;
@ -3543,6 +3718,7 @@ exports.makeSelectPendingByUri = makeSelectPendingByUri;
exports.makeSelectQueryWithOptions = makeSelectQueryWithOptions; exports.makeSelectQueryWithOptions = makeSelectQueryWithOptions;
exports.makeSelectRecommendedContentForUri = makeSelectRecommendedContentForUri; exports.makeSelectRecommendedContentForUri = makeSelectRecommendedContentForUri;
exports.makeSelectSearchUris = makeSelectSearchUris; exports.makeSelectSearchUris = makeSelectSearchUris;
exports.makeSelectStreamingUrlForUri = makeSelectStreamingUrlForUri;
exports.makeSelectThumbnailForUri = makeSelectThumbnailForUri; exports.makeSelectThumbnailForUri = makeSelectThumbnailForUri;
exports.makeSelectTitleForUri = makeSelectTitleForUri; exports.makeSelectTitleForUri = makeSelectTitleForUri;
exports.makeSelectTotalItemsForChannel = makeSelectTotalItemsForChannel; exports.makeSelectTotalItemsForChannel = makeSelectTotalItemsForChannel;
@ -3572,6 +3748,7 @@ exports.selectDraftTransactionAddress = selectDraftTransactionAddress;
exports.selectDraftTransactionAmount = selectDraftTransactionAmount; exports.selectDraftTransactionAmount = selectDraftTransactionAmount;
exports.selectDraftTransactionError = selectDraftTransactionError; exports.selectDraftTransactionError = selectDraftTransactionError;
exports.selectError = selectError; exports.selectError = selectError;
exports.selectFailedPurchaseUris = selectFailedPurchaseUris;
exports.selectFetchingMyChannels = selectFetchingMyChannels; exports.selectFetchingMyChannels = selectFetchingMyChannels;
exports.selectFileInfosByOutpoint = selectFileInfosByOutpoint; exports.selectFileInfosByOutpoint = selectFileInfosByOutpoint;
exports.selectFileInfosDownloaded = selectFileInfosDownloaded; exports.selectFileInfosDownloaded = selectFileInfosDownloaded;
@ -3585,6 +3762,7 @@ exports.selectIsFetchingFileListDownloadedOrPublished = selectIsFetchingFileList
exports.selectIsFetchingTransactions = selectIsFetchingTransactions; exports.selectIsFetchingTransactions = selectIsFetchingTransactions;
exports.selectIsSearching = selectIsSearching; exports.selectIsSearching = selectIsSearching;
exports.selectIsSendingSupport = selectIsSendingSupport; exports.selectIsSendingSupport = selectIsSendingSupport;
exports.selectLastPurchasedUri = selectLastPurchasedUri;
exports.selectMyActiveClaims = selectMyActiveClaims; exports.selectMyActiveClaims = selectMyActiveClaims;
exports.selectMyChannelClaims = selectMyChannelClaims; exports.selectMyChannelClaims = selectMyChannelClaims;
exports.selectMyClaims = selectMyClaims; exports.selectMyClaims = selectMyClaims;
@ -3594,6 +3772,8 @@ exports.selectMyClaimsWithoutChannels = selectMyClaimsWithoutChannels;
exports.selectPendingById = selectPendingById; exports.selectPendingById = selectPendingById;
exports.selectPendingClaims = selectPendingClaims; exports.selectPendingClaims = selectPendingClaims;
exports.selectPlayingUri = selectPlayingUri; exports.selectPlayingUri = selectPlayingUri;
exports.selectPurchasedStreamingUrls = selectPurchasedStreamingUrls;
exports.selectPurchasedUris = selectPurchasedUris;
exports.selectReceiveAddress = selectReceiveAddress; exports.selectReceiveAddress = selectReceiveAddress;
exports.selectRecentTransactions = selectRecentTransactions; exports.selectRecentTransactions = selectRecentTransactions;
exports.selectResolvingUris = selectResolvingUris; exports.selectResolvingUris = selectResolvingUris;

View file

@ -24,6 +24,7 @@ declare type FileListItem = {
stopped: false, stopped: false,
stream_hash: string, stream_hash: string,
stream_name: string, stream_name: string,
streaming_url: string,
suggested_file_name: string, suggested_file_name: string,
total_bytes: number, total_bytes: number,
total_bytes_lower_bound: number, total_bytes_lower_bound: number,
@ -33,3 +34,24 @@ declare type FileListItem = {
txid: string, txid: string,
written_bytes: number, written_bytes: number,
}; };
declare type FileState = {
failedPurchaseUris: Array<string>,
purchasedUris: Array<string>,
purchasedStreamingUrls: {},
};
declare type PurchaseUriCompleted = {
type: ACTIONS.PURCHASE_URI_COMPLETED,
data: {
uri: string,
streamingUrl: string,
},
};
declare type PurchaseUriFailed = {
type: ACTIONS.PURCHASE_URI_FAILED,
data: {
uri: string
},
};

22
flow-typed/File.js vendored
View file

@ -24,6 +24,7 @@ declare type FileListItem = {
stopped: false, stopped: false,
stream_hash: string, stream_hash: string,
stream_name: string, stream_name: string,
streaming_url: string,
suggested_file_name: string, suggested_file_name: string,
total_bytes: number, total_bytes: number,
total_bytes_lower_bound: number, total_bytes_lower_bound: number,
@ -33,3 +34,24 @@ declare type FileListItem = {
txid: string, txid: string,
written_bytes: number, written_bytes: number,
}; };
declare type FileState = {
failedPurchaseUris: Array<string>,
purchasedUris: Array<string>,
purchasedStreamingUrls: {},
};
declare type PurchaseUriCompleted = {
type: ACTIONS.PURCHASE_URI_COMPLETED,
data: {
uri: string,
streamingUrl: string,
},
};
declare type PurchaseUriFailed = {
type: ACTIONS.PURCHASE_URI_FAILED,
data: {
uri: string
},
};

View file

@ -106,6 +106,12 @@ export const FETCH_AVAILABILITY_STARTED = 'FETCH_AVAILABILITY_STARTED';
export const FETCH_AVAILABILITY_COMPLETED = 'FETCH_AVAILABILITY_COMPLETED'; export const FETCH_AVAILABILITY_COMPLETED = 'FETCH_AVAILABILITY_COMPLETED';
export const FILE_DELETE = 'FILE_DELETE'; export const FILE_DELETE = 'FILE_DELETE';
export const SET_FILE_LIST_SORT = 'SET_FILE_LIST_SORT'; export const SET_FILE_LIST_SORT = 'SET_FILE_LIST_SORT';
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 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';
@ -217,3 +223,8 @@ export const CREATE_ERROR = 'CREATE_ERROR';
export const DISMISS_ERROR = 'DISMISS_ERROR'; export const DISMISS_ERROR = 'DISMISS_ERROR';
export const FETCH_DATE = 'FETCH_DATE'; export const FETCH_DATE = 'FETCH_DATE';
// Cost info
export const FETCH_COST_INFO_STARTED = 'FETCH_COST_INFO_STARTED';
export const FETCH_COST_INFO_COMPLETED = 'FETCH_COST_INFO_COMPLETED';
export const FETCH_COST_INFO_FAILED = 'FETCH_COST_INFO_FAILED';

View file

@ -47,6 +47,8 @@ export {
doCreateChannel, doCreateChannel,
} from 'redux/actions/claims'; } from 'redux/actions/claims';
export { doPurchaseUri, doFileGet } from 'redux/actions/file';
export { export {
doFetchFileInfo, doFetchFileInfo,
doFileList, doFileList,
@ -93,6 +95,7 @@ export { isClaimNsfw } from 'util/claim';
// reducers // reducers
export { claimsReducer } from 'redux/reducers/claims'; export { claimsReducer } from 'redux/reducers/claims';
export { fileReducer } from 'redux/reducers/file';
export { fileInfoReducer } from 'redux/reducers/file_info'; export { fileInfoReducer } from 'redux/reducers/file_info';
export { notificationsReducer } from 'redux/reducers/notifications'; export { notificationsReducer } from 'redux/reducers/notifications';
export { searchReducer } from 'redux/reducers/search'; export { searchReducer } from 'redux/reducers/search';
@ -104,6 +107,14 @@ export { makeSelectContentPositionForUri } from 'redux/selectors/content';
export { selectToast, selectError } from 'redux/selectors/notifications'; export { selectToast, selectError } from 'redux/selectors/notifications';
export {
selectFailedPurchaseUris,
selectPurchasedUris,
selectPurchasedStreamingUrls,
selectLastPurchasedUri,
makeSelectStreamingUrlForUri,
} from 'redux/selectors/file';
export { export {
makeSelectClaimForUri, makeSelectClaimForUri,
makeSelectClaimIsMine, makeSelectClaimIsMine,

104
src/redux/actions/file.js Normal file
View file

@ -0,0 +1,104 @@
// @flow
import * as ACTIONS from 'constants/action_types';
import Lbry from 'lbry';
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';
type Dispatch = (action: any) => any;
type GetState = () => { file: FileState };
export function doFileGet(uri: string, saveFile: boolean = true) {
return (dispatch: Dispatch) => {
dispatch({
type: ACTIONS.LOADING_FILE_STARTED,
data: {
uri,
},
});
// 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';
if (timeout) {
dispatch({
type: ACTIONS.LOADING_FILE_FAILED,
data: { uri },
});
dispatch({
type: ACTIONS.PURCHASE_URI_FAILED,
data: { uri },
});
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 },
});
}
})
.catch(() => {
dispatch({
type: ACTIONS.LOADING_FILE_FAILED,
data: { uri },
});
dispatch({
type: ACTIONS.PURCHASE_URI_FAILED,
data: { uri },
});
dispatch(
doToast({
message: `Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.com/faq/support for support.`,
isError: true,
})
);
});
};
}
export function doPurchaseUri(uri: string, costInfo: { cost: number }, saveFile: boolean = true) {
return (dispatch: Dispatch, getState: GetState) => {
dispatch({
type: ACTIONS.PURCHASE_URI_STARTED,
data: { uri },
});
const state = getState();
const balance = selectBalance(state);
const fileInfo = makeSelectFileInfoForUri(uri)(state);
const downloadingByOutpoint = selectDownloadingByOutpoint(state);
const alreadyDownloading = fileInfo && !!downloadingByOutpoint[fileInfo.outpoint];
const alreadyStreaming = makeSelectStreamingUrlForUri(uri)(state);
if (alreadyDownloading || alreadyStreaming) {
dispatch({
type: ACTIONS.PURCHASE_URI_FAILED,
data: { uri, error: `Already fetching uri: ${uri}` },
});
Promise.resolve();
return;
}
const { cost } = costInfo;
if (cost > balance) {
dispatch({
type: ACTIONS.PURCHASE_URI_FAILED,
data: { uri, error: 'Insufficient credits' },
});
Promise.resolve();
return;
}
dispatch(doFileGet(uri, saveFile));
};
}

View file

@ -0,0 +1,58 @@
// @flow
import * as ACTIONS from 'constants/action_types';
const reducers = {};
const defaultState = {
failedPurchaseUris: [],
purchasedUris: [],
purchasedStreamingUrls: {},
};
reducers[ACTIONS.PURCHASE_URI_COMPLETED] = (
state: FileState,
action: PurchaseUriCompleted
): FileState => {
const { uri, streamingUrl } = 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);
}
if (newFailedPurchaseUris.includes(uri)) {
newFailedPurchaseUris.splice(newFailedPurchaseUris.indexOf(uri), 1);
}
if (streamingUrl) {
newPurchasedStreamingUrls[uri] = streamingUrl;
}
return {
...state,
failedPurchaseUris: newFailedPurchaseUris,
purchasedUris: newPurchasedUris,
purchasedStreamingUrls: newPurchasedStreamingUrls,
};
};
reducers[ACTIONS.PURCHASE_URI_FAILED] = (
state: FileState,
action: PurchaseUriFailed
): FileState => {
const { uri } = action.data;
const newFailedPurchaseUris = state.failedPurchaseUris.slice();
if (!newFailedPurchaseUris.includes(uri)) {
newFailedPurchaseUris.push(uri);
}
return {
...state,
failedPurchaseUris: newFailedPurchaseUris,
};
};
export function fileReducer(state: FileState = defaultState, action: any) {
const handler = reducers[action.type];
if (handler) return handler(state, action);
return state;
}

View file

@ -0,0 +1,33 @@
// @flow
import { createSelector } from 'reselect';
type State = { file: FileState };
export const selectState = (state: State): FileState => state.file || {};
export const selectFailedPurchaseUris: (state: State) => Array<string> = createSelector(
selectState,
state => state.failedPurchaseUris
);
export const selectPurchasedUris: (state: State) => Array<string> = createSelector(
selectState,
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) => {}) =>
createSelector(
selectPurchasedStreamingUrls,
streamingUrls => streamingUrls && streamingUrls[uri]
);