move file actions from lbry-redux
This commit is contained in:
parent
4bc4a965d9
commit
b44be39252
7 changed files with 231 additions and 15 deletions
78
flow-typed/File.js
vendored
Normal file
78
flow-typed/File.js
vendored
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
declare type FileListItem = {
|
||||||
|
metadata: StreamMetadata,
|
||||||
|
added_on: number,
|
||||||
|
blobs_completed: number,
|
||||||
|
blobs_in_stream: number,
|
||||||
|
blobs_remaining: number,
|
||||||
|
channel_claim_id: string,
|
||||||
|
channel_name: string,
|
||||||
|
claim_id: string,
|
||||||
|
claim_name: string,
|
||||||
|
completed: false,
|
||||||
|
content_fee?: { txid: string },
|
||||||
|
purchase_receipt?: { txid: string, amount: string },
|
||||||
|
download_directory: string,
|
||||||
|
download_path: string,
|
||||||
|
file_name: string,
|
||||||
|
key: string,
|
||||||
|
mime_type: string,
|
||||||
|
nout: number,
|
||||||
|
outpoint: string,
|
||||||
|
points_paid: number,
|
||||||
|
protobuf: string,
|
||||||
|
reflector_progress: number,
|
||||||
|
sd_hash: string,
|
||||||
|
status: string,
|
||||||
|
stopped: false,
|
||||||
|
stream_hash: string,
|
||||||
|
stream_name: string,
|
||||||
|
streaming_url: string,
|
||||||
|
suggested_file_name: string,
|
||||||
|
total_bytes: number,
|
||||||
|
total_bytes_lower_bound: number,
|
||||||
|
is_fully_reflected: boolean,
|
||||||
|
// TODO: sdk plans to change `tx`
|
||||||
|
// It isn't currently used by the apps
|
||||||
|
tx: {},
|
||||||
|
txid: string,
|
||||||
|
uploading_to_reflector: boolean,
|
||||||
|
written_bytes: number,
|
||||||
|
};
|
||||||
|
|
||||||
|
declare type FileState = {
|
||||||
|
failedPurchaseUris: Array<string>,
|
||||||
|
purchasedUris: Array<string>,
|
||||||
|
};
|
||||||
|
|
||||||
|
declare type PurchaseUriCompleted = {
|
||||||
|
type: ACTIONS.PURCHASE_URI_COMPLETED,
|
||||||
|
data: {
|
||||||
|
uri: string,
|
||||||
|
streamingUrl: string,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
declare type PurchaseUriFailed = {
|
||||||
|
type: ACTIONS.PURCHASE_URI_FAILED,
|
||||||
|
data: {
|
||||||
|
uri: string,
|
||||||
|
error: any,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
declare type PurchaseUriStarted = {
|
||||||
|
type: ACTIONS.PURCHASE_URI_STARTED,
|
||||||
|
data: {
|
||||||
|
uri: string,
|
||||||
|
streamingUrl: string,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
declare type DeletePurchasedUri = {
|
||||||
|
type: ACTIONS.CLEAR_PURCHASED_URI_SUCCESS,
|
||||||
|
data: {
|
||||||
|
uri: string,
|
||||||
|
},
|
||||||
|
};
|
|
@ -6,7 +6,6 @@ import {
|
||||||
makeSelectClaimIsMine,
|
makeSelectClaimIsMine,
|
||||||
makeSelectClaimIsPending,
|
makeSelectClaimIsPending,
|
||||||
makeSelectClaimIsNsfw,
|
makeSelectClaimIsNsfw,
|
||||||
doFileGet,
|
|
||||||
makeSelectReflectingClaimForUri,
|
makeSelectReflectingClaimForUri,
|
||||||
makeSelectClaimWasPurchased,
|
makeSelectClaimWasPurchased,
|
||||||
makeSelectStreamingUrlForUri,
|
makeSelectStreamingUrlForUri,
|
||||||
|
@ -25,7 +24,7 @@ import { selectShowMatureContent } from 'redux/selectors/settings';
|
||||||
import { makeSelectHasVisitedUri } from 'redux/selectors/content';
|
import { makeSelectHasVisitedUri } from 'redux/selectors/content';
|
||||||
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
|
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
|
||||||
import { selectModerationBlockList } from 'redux/selectors/comments';
|
import { selectModerationBlockList } from 'redux/selectors/comments';
|
||||||
|
import { doFileGet } from 'redux/actions/file';
|
||||||
import ClaimPreview from './view';
|
import ClaimPreview from './view';
|
||||||
import formatMediaDuration from 'util/formatMediaDuration';
|
import formatMediaDuration from 'util/formatMediaDuration';
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import {
|
||||||
makeSelectIsUriResolving,
|
makeSelectIsUriResolving,
|
||||||
makeSelectThumbnailForUri,
|
makeSelectThumbnailForUri,
|
||||||
makeSelectTitleForUri,
|
makeSelectTitleForUri,
|
||||||
doFileGet,
|
|
||||||
makeSelectChannelForClaimUri,
|
makeSelectChannelForClaimUri,
|
||||||
makeSelectClaimIsNsfw,
|
makeSelectClaimIsNsfw,
|
||||||
makeSelectClaimIsStreamPlaceholder,
|
makeSelectClaimIsStreamPlaceholder,
|
||||||
|
@ -14,6 +13,7 @@ import {
|
||||||
import { selectMutedChannels } from 'redux/selectors/blocked';
|
import { selectMutedChannels } from 'redux/selectors/blocked';
|
||||||
import { makeSelectViewCountForUri, selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc';
|
import { makeSelectViewCountForUri, selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc';
|
||||||
import { makeSelectIsActiveLivestream } from 'redux/selectors/livestream';
|
import { makeSelectIsActiveLivestream } from 'redux/selectors/livestream';
|
||||||
|
import { doFileGet } from 'redux/actions/file';
|
||||||
import { selectShowMatureContent } from 'redux/selectors/settings';
|
import { selectShowMatureContent } from 'redux/selectors/settings';
|
||||||
import ClaimPreviewTile from './view';
|
import ClaimPreviewTile from './view';
|
||||||
import formatMediaDuration from 'util/formatMediaDuration';
|
import formatMediaDuration from 'util/formatMediaDuration';
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||||
import { selectPurchaseUriSuccess, doClearPurchasedUriSuccess } from 'lbry-redux';
|
import { selectPurchaseUriSuccess } from 'lbry-redux';
|
||||||
import { selectFollowedTags } from 'redux/selectors/tags';
|
import { selectFollowedTags } from 'redux/selectors/tags';
|
||||||
import { selectUserVerifiedEmail, selectUser } from 'redux/selectors/user';
|
import { selectUserVerifiedEmail, selectUser } from 'redux/selectors/user';
|
||||||
import { selectHomepageData, selectLanguage } from 'redux/selectors/settings';
|
import { selectHomepageData, selectLanguage } from 'redux/selectors/settings';
|
||||||
import { doSignOut } from 'redux/actions/app';
|
import { doSignOut } from 'redux/actions/app';
|
||||||
|
import { doClearPurchasedUriSuccess } from 'redux/actions/file';
|
||||||
|
|
||||||
import { selectUnseenNotificationCount } from 'redux/selectors/notifications';
|
import { selectUnseenNotificationCount } from 'redux/selectors/notifications';
|
||||||
|
|
||||||
import SideNavigation from './view';
|
import SideNavigation from './view';
|
||||||
|
|
|
@ -120,6 +120,13 @@ export const PLAY_VIDEO_STARTED = 'PLAY_VIDEO_STARTED';
|
||||||
export const FETCH_AVAILABILITY_STARTED = 'FETCH_AVAILABILITY_STARTED';
|
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 FETCH_FILE_INFO_FAILED = 'FETCH_FILE_INFO_FAILED';
|
||||||
|
export const DOWNLOADING_CANCELED = 'DOWNLOADING_CANCELED';
|
||||||
|
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 CLEAR_PURCHASED_URI_SUCCESS = 'CLEAR_PURCHASED_URI_SUCCESS';
|
||||||
|
|
||||||
// Search
|
// Search
|
||||||
export const SEARCH_START = 'SEARCH_START';
|
export const SEARCH_START = 'SEARCH_START';
|
||||||
|
|
|
@ -10,7 +10,6 @@ import {
|
||||||
SETTINGS,
|
SETTINGS,
|
||||||
makeSelectFileInfoForUri,
|
makeSelectFileInfoForUri,
|
||||||
selectFileInfosByOutpoint,
|
selectFileInfosByOutpoint,
|
||||||
doPurchaseUri,
|
|
||||||
makeSelectUriIsStreamable,
|
makeSelectUriIsStreamable,
|
||||||
selectDownloadingByOutpoint,
|
selectDownloadingByOutpoint,
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
|
@ -19,6 +18,7 @@ import {
|
||||||
doToast,
|
doToast,
|
||||||
makeSelectUrlsForCollectionId,
|
makeSelectUrlsForCollectionId,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
|
import { doPurchaseUri } from 'redux/actions/file';
|
||||||
import { makeSelectCostInfoForUri, Lbryio } from 'lbryinc';
|
import { makeSelectCostInfoForUri, Lbryio } from 'lbryinc';
|
||||||
import { makeSelectClientSetting, selectosNotificationsEnabled, selectDaemonSettings } from 'redux/selectors/settings';
|
import { makeSelectClientSetting, selectosNotificationsEnabled, selectDaemonSettings } from 'redux/selectors/settings';
|
||||||
|
|
||||||
|
@ -117,8 +117,8 @@ export function doSetPlayingUri({
|
||||||
uri: ?string,
|
uri: ?string,
|
||||||
source?: string,
|
source?: string,
|
||||||
commentId?: string,
|
commentId?: string,
|
||||||
pathname: string,
|
pathname?: string,
|
||||||
collectionId: string,
|
collectionId?: string,
|
||||||
}) {
|
}) {
|
||||||
return (dispatch: Dispatch) => {
|
return (dispatch: Dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -140,7 +140,7 @@ export function doPurchaseUriWrapper(uri: string, cost: number, saveFile: boolea
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(doPurchaseUri(uri, { costInfo: cost }, saveFile, onSuccess));
|
dispatch(doPurchaseUri(uri, { cost }, saveFile, onSuccess));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// @flow
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
import { shell } from 'electron';
|
import { shell } from 'electron';
|
||||||
|
@ -7,22 +8,28 @@ import {
|
||||||
batchActions,
|
batchActions,
|
||||||
doAbandonClaim,
|
doAbandonClaim,
|
||||||
makeSelectFileInfoForUri,
|
makeSelectFileInfoForUri,
|
||||||
|
selectDownloadingByOutpoint,
|
||||||
|
makeSelectStreamingUrlForUri,
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
|
selectBalance,
|
||||||
ABANDON_STATES,
|
ABANDON_STATES,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { doHideModal } from 'redux/actions/app';
|
import { doHideModal } from 'redux/actions/app';
|
||||||
import { goBack } from 'connected-react-router';
|
import { goBack } from 'connected-react-router';
|
||||||
import { doSetPlayingUri } from 'redux/actions/content';
|
import { doSetPlayingUri } from 'redux/actions/content';
|
||||||
import { selectPlayingUri } from 'redux/selectors/content';
|
import { selectPlayingUri } from 'redux/selectors/content';
|
||||||
|
import { doToast } from 'redux/actions/notifications';
|
||||||
|
type Dispatch = (action: any) => any;
|
||||||
|
type GetState = () => { file: FileState };
|
||||||
|
|
||||||
export function doOpenFileInFolder(path) {
|
export function doOpenFileInFolder(path: string) {
|
||||||
return () => {
|
return () => {
|
||||||
shell.showItemInFolder(path);
|
shell.showItemInFolder(path);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doOpenFileInShell(path) {
|
export function doOpenFileInShell(path: string) {
|
||||||
return (dispatch) => {
|
return (dispatch: Dispatch) => {
|
||||||
const success = shell.openPath(path);
|
const success = shell.openPath(path);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
dispatch(doOpenFileInFolder(path));
|
dispatch(doOpenFileInFolder(path));
|
||||||
|
@ -30,8 +37,8 @@ export function doOpenFileInShell(path) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim, cb) {
|
export function doDeleteFile(outpoint: string, deleteFromComputer?: boolean, abandonClaim?: boolean, cb: any) {
|
||||||
return (dispatch) => {
|
return (dispatch: Dispatch) => {
|
||||||
if (abandonClaim) {
|
if (abandonClaim) {
|
||||||
const [txid, nout] = outpoint.split(':');
|
const [txid, nout] = outpoint.split(':');
|
||||||
dispatch(doAbandonClaim(txid, Number(nout), cb));
|
dispatch(doAbandonClaim(txid, Number(nout), cb));
|
||||||
|
@ -53,8 +60,13 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim, cb) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doDeleteFileAndMaybeGoBack(uri, deleteFromComputer, abandonClaim, doGoBack) {
|
export function doDeleteFileAndMaybeGoBack(
|
||||||
return (dispatch, getState) => {
|
uri: string,
|
||||||
|
deleteFromComputer?: boolean,
|
||||||
|
abandonClaim?: boolean,
|
||||||
|
doGoBack: (any) => void
|
||||||
|
) {
|
||||||
|
return (dispatch: Dispatch, getState: GetState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const playingUri = selectPlayingUri(state);
|
const playingUri = selectPlayingUri(state);
|
||||||
const { outpoint } = makeSelectFileInfoForUri(uri)(state) || '';
|
const { outpoint } = makeSelectFileInfoForUri(uri)(state) || '';
|
||||||
|
@ -88,3 +100,121 @@ export function doDeleteFileAndMaybeGoBack(uri, deleteFromComputer, abandonClaim
|
||||||
dispatch(batchActions(...actions));
|
dispatch(batchActions(...actions));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.FETCH_FILE_INFO_STARTED,
|
||||||
|
data: {
|
||||||
|
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' || streamInfo.error === 'Timeout';
|
||||||
|
if (timeout) {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.FETCH_FILE_INFO_FAILED,
|
||||||
|
data: { outpoint },
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch(doToast({ message: `File timeout for uri ${uri}`, isError: true }));
|
||||||
|
} else {
|
||||||
|
if (streamInfo.purchase_receipt || streamInfo.content_fee) {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.PURCHASE_URI_COMPLETED,
|
||||||
|
data: { uri, purchaseReceipt: streamInfo.purchase_receipt || streamInfo.content_fee },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.FETCH_FILE_INFO_COMPLETED,
|
||||||
|
data: {
|
||||||
|
fileInfo: streamInfo,
|
||||||
|
outpoint: outpoint,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess(streamInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.PURCHASE_URI_FAILED,
|
||||||
|
data: { uri, error },
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.FETCH_FILE_INFO_FAILED,
|
||||||
|
data: { outpoint },
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch(
|
||||||
|
doToast({
|
||||||
|
message: `Failed to view ${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,
|
||||||
|
onSuccess?: (GetResponse) => any
|
||||||
|
) {
|
||||||
|
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 (!saveFile && (alreadyDownloading || alreadyStreaming)) {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.PURCHASE_URI_FAILED,
|
||||||
|
data: { uri, error: `Already fetching uri: ${uri}` },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (onSuccess) {
|
||||||
|
onSuccess(fileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { cost } = costInfo;
|
||||||
|
if (parseFloat(cost) > balance) {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.PURCHASE_URI_FAILED,
|
||||||
|
data: { uri, error: 'Insufficient credits' },
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.resolve();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(doFileGet(uri, saveFile, onSuccess));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function doClearPurchasedUriSuccess() {
|
||||||
|
return {
|
||||||
|
type: ACTIONS.CLEAR_PURCHASED_URI_SUCCESS,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue