-- Revert to allow restoring commits ---
This reverts commit cb6a044584
.
This commit is contained in:
parent
d649e3563f
commit
263c09500f
27 changed files with 325 additions and 814 deletions
|
@ -8,7 +8,6 @@ const config = {
|
||||||
WEB_SERVER_PORT: process.env.WEB_SERVER_PORT,
|
WEB_SERVER_PORT: process.env.WEB_SERVER_PORT,
|
||||||
LBRY_WEB_API: process.env.LBRY_WEB_API, //api.na-backend.odysee.com',
|
LBRY_WEB_API: process.env.LBRY_WEB_API, //api.na-backend.odysee.com',
|
||||||
LBRY_WEB_PUBLISH_API: process.env.LBRY_WEB_PUBLISH_API,
|
LBRY_WEB_PUBLISH_API: process.env.LBRY_WEB_PUBLISH_API,
|
||||||
LBRY_WEB_PUBLISH_API_V2: process.env.LBRY_WEB_PUBLISH_API_V2,
|
|
||||||
LBRY_API_URL: process.env.LBRY_API_URL, //api.lbry.com',
|
LBRY_API_URL: process.env.LBRY_API_URL, //api.lbry.com',
|
||||||
LBRY_WEB_STREAMING_API: process.env.LBRY_WEB_STREAMING_API, //cdn.lbryplayer.xyz',
|
LBRY_WEB_STREAMING_API: process.env.LBRY_WEB_STREAMING_API, //cdn.lbryplayer.xyz',
|
||||||
LBRY_WEB_BUFFER_API: process.env.LBRY_WEB_BUFFER_API,
|
LBRY_WEB_BUFFER_API: process.env.LBRY_WEB_BUFFER_API,
|
||||||
|
|
|
@ -83,6 +83,9 @@ export const SYNC_APPLY_FAILED = 'SYNC_APPLY_FAILED';
|
||||||
export const SYNC_APPLY_BAD_PASSWORD = 'SYNC_APPLY_BAD_PASSWORD';
|
export const SYNC_APPLY_BAD_PASSWORD = 'SYNC_APPLY_BAD_PASSWORD';
|
||||||
export const SYNC_RESET = 'SYNC_RESET';
|
export const SYNC_RESET = 'SYNC_RESET';
|
||||||
|
|
||||||
|
// Lbry.tv
|
||||||
|
export const UPDATE_UPLOAD_PROGRESS = 'UPDATE_UPLOAD_PROGRESS';
|
||||||
|
|
||||||
// User
|
// User
|
||||||
export const GENERATE_AUTH_TOKEN_FAILURE = 'GENERATE_AUTH_TOKEN_FAILURE';
|
export const GENERATE_AUTH_TOKEN_FAILURE = 'GENERATE_AUTH_TOKEN_FAILURE';
|
||||||
export const GENERATE_AUTH_TOKEN_STARTED = 'GENERATE_AUTH_TOKEN_STARTED';
|
export const GENERATE_AUTH_TOKEN_STARTED = 'GENERATE_AUTH_TOKEN_STARTED';
|
||||||
|
|
|
@ -27,6 +27,7 @@ export {
|
||||||
doResetSync,
|
doResetSync,
|
||||||
doSyncEncryptAndDecrypt,
|
doSyncEncryptAndDecrypt,
|
||||||
} from 'redux/actions/sync';
|
} from 'redux/actions/sync';
|
||||||
|
export { doUpdateUploadProgress } from './redux/actions/web';
|
||||||
|
|
||||||
// reducers
|
// reducers
|
||||||
export { authReducer } from './redux/reducers/auth';
|
export { authReducer } from './redux/reducers/auth';
|
||||||
|
@ -36,6 +37,7 @@ export { filteredReducer } from './redux/reducers/filtered';
|
||||||
// export { homepageReducer } from './redux/reducers/homepage';
|
// export { homepageReducer } from './redux/reducers/homepage';
|
||||||
export { statsReducer } from './redux/reducers/stats';
|
export { statsReducer } from './redux/reducers/stats';
|
||||||
export { syncReducer } from './redux/reducers/sync';
|
export { syncReducer } from './redux/reducers/sync';
|
||||||
|
export { webReducer } from './redux/reducers/web';
|
||||||
|
|
||||||
// selectors
|
// selectors
|
||||||
export { selectAuthToken, selectIsAuthenticating } from './redux/selectors/auth';
|
export { selectAuthToken, selectIsAuthenticating } from './redux/selectors/auth';
|
||||||
|
@ -68,3 +70,4 @@ export {
|
||||||
selectSyncApplyErrorMessage,
|
selectSyncApplyErrorMessage,
|
||||||
selectSyncApplyPasswordError,
|
selectSyncApplyPasswordError,
|
||||||
} from './redux/selectors/sync';
|
} from './redux/selectors/sync';
|
||||||
|
export { selectCurrentUploads, selectUploadCount } from './redux/selectors/web';
|
||||||
|
|
12
extras/lbryinc/redux/actions/web.js
Normal file
12
extras/lbryinc/redux/actions/web.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// @flow
|
||||||
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
|
export const doUpdateUploadProgress = (
|
||||||
|
progress: string,
|
||||||
|
params: { [key: string]: any },
|
||||||
|
xhr: any
|
||||||
|
) => (dispatch: Dispatch) =>
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.UPDATE_UPLOAD_PROGRESS,
|
||||||
|
data: { progress, params, xhr },
|
||||||
|
});
|
62
extras/lbryinc/redux/reducers/web.js
Normal file
62
extras/lbryinc/redux/reducers/web.js
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// @flow
|
||||||
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
|
||||||
|
/*
|
||||||
|
test mock:
|
||||||
|
currentUploads: {
|
||||||
|
'test#upload': {
|
||||||
|
progress: 50,
|
||||||
|
params: {
|
||||||
|
name: 'steve',
|
||||||
|
thumbnail_url: 'https://dev2.spee.ch/4/KMNtoSZ009fawGz59VG8PrID.jpeg',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type Params = {
|
||||||
|
channel?: string,
|
||||||
|
name: string,
|
||||||
|
thumbnail_url: ?string,
|
||||||
|
title: ?string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UploadItem = {
|
||||||
|
progess: string,
|
||||||
|
params: Params,
|
||||||
|
xhr?: any,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TvState = {
|
||||||
|
currentUploads: { [key: string]: UploadItem },
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducers = {};
|
||||||
|
|
||||||
|
const defaultState: TvState = {
|
||||||
|
currentUploads: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
reducers[ACTIONS.UPDATE_UPLOAD_PROGRESS] = (state: TvState, action) => {
|
||||||
|
const { progress, params, xhr } = action.data;
|
||||||
|
const key = params.channel ? `${params.name}#${params.channel}` : `${params.name}#anonymous`;
|
||||||
|
let currentUploads;
|
||||||
|
if (!progress) {
|
||||||
|
currentUploads = Object.assign({}, state.currentUploads);
|
||||||
|
Object.keys(currentUploads).forEach(k => {
|
||||||
|
if (k === key) {
|
||||||
|
delete currentUploads[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
currentUploads = Object.assign({}, state.currentUploads);
|
||||||
|
currentUploads[key] = { progress, params, xhr };
|
||||||
|
}
|
||||||
|
return { ...state, currentUploads };
|
||||||
|
};
|
||||||
|
|
||||||
|
export function webReducer(state: TvState = defaultState, action: any) {
|
||||||
|
const handler = reducers[action.type];
|
||||||
|
if (handler) return handler(state, action);
|
||||||
|
return state;
|
||||||
|
}
|
10
extras/lbryinc/redux/selectors/web.js
Normal file
10
extras/lbryinc/redux/selectors/web.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
|
const selectState = (state) => state.web || {};
|
||||||
|
|
||||||
|
export const selectCurrentUploads = (state) => selectState(state).currentUploads;
|
||||||
|
|
||||||
|
export const selectUploadCount = createSelector(
|
||||||
|
selectCurrentUploads,
|
||||||
|
(currentUploads) => currentUploads && Object.keys(currentUploads).length
|
||||||
|
);
|
21
flow-typed/publish.js
vendored
21
flow-typed/publish.js
vendored
|
@ -52,24 +52,3 @@ declare type PublishParams = {
|
||||||
nsfw: boolean,
|
nsfw: boolean,
|
||||||
tags: Array<Tag>,
|
tags: Array<Tag>,
|
||||||
};
|
};
|
||||||
|
|
||||||
declare type TusUploader = any;
|
|
||||||
|
|
||||||
declare type FileUploadSdkParams = {
|
|
||||||
file_path: string,
|
|
||||||
name: ?string,
|
|
||||||
preview?: boolean,
|
|
||||||
remote_url?: string,
|
|
||||||
thumbnail_url?: string,
|
|
||||||
title?: string,
|
|
||||||
};
|
|
||||||
|
|
||||||
declare type FileUploadItem = {
|
|
||||||
params: FileUploadSdkParams,
|
|
||||||
file: File,
|
|
||||||
fileFingerprint: string,
|
|
||||||
progress: string,
|
|
||||||
status?: string,
|
|
||||||
uploader?: TusUploader | XMLHttpRequest,
|
|
||||||
resumable: boolean,
|
|
||||||
};
|
|
||||||
|
|
|
@ -68,7 +68,6 @@
|
||||||
"rss": "^1.2.2",
|
"rss": "^1.2.2",
|
||||||
"source-map-explorer": "^2.5.2",
|
"source-map-explorer": "^2.5.2",
|
||||||
"tempy": "^0.6.0",
|
"tempy": "^0.6.0",
|
||||||
"tus-js-client": "^2.3.0",
|
|
||||||
"videojs-contrib-ads": "^6.9.0",
|
"videojs-contrib-ads": "^6.9.0",
|
||||||
"videojs-ima": "^1.11.0",
|
"videojs-ima": "^1.11.0",
|
||||||
"videojs-ima-player": "^0.5.6",
|
"videojs-ima-player": "^0.5.6",
|
||||||
|
|
|
@ -1291,16 +1291,6 @@
|
||||||
"Select a file to upload": "Select a file to upload",
|
"Select a file to upload": "Select a file to upload",
|
||||||
"Select file to upload": "Select file to upload",
|
"Select file to upload": "Select file to upload",
|
||||||
"Url copied.": "Url copied.",
|
"Url copied.": "Url copied.",
|
||||||
"Failed to initiate upload (%err%)": "Failed to initiate upload (%err%)",
|
|
||||||
"Invalid file": "Invalid file",
|
|
||||||
"It appears to be a different or modified file.": "It appears to be a different or modified file.",
|
|
||||||
"Please select the same file from the initial upload.": "Please select the same file from the initial upload.",
|
|
||||||
"Cancel upload": "Cancel upload",
|
|
||||||
"Cancel and remove the selected upload?": "Cancel and remove the selected upload?",
|
|
||||||
"Select the file to resume upload...": "Select the file to resume upload...",
|
|
||||||
"Stopped.": "Stopped.",
|
|
||||||
"Resume": "Resume",
|
|
||||||
"Retrying...": "Retrying...",
|
|
||||||
"Uploading...": "Uploading...",
|
"Uploading...": "Uploading...",
|
||||||
"Creating...": "Creating...",
|
"Creating...": "Creating...",
|
||||||
"Use a URL": "Use a URL",
|
"Use a URL": "Use a URL",
|
||||||
|
@ -1440,6 +1430,7 @@
|
||||||
"Log in to %SITE_NAME%": "Log in to %SITE_NAME%",
|
"Log in to %SITE_NAME%": "Log in to %SITE_NAME%",
|
||||||
"Log in": "Log in",
|
"Log in": "Log in",
|
||||||
"Not Yet": "Not Yet",
|
"Not Yet": "Not Yet",
|
||||||
|
"Preparing...": "Preparing...",
|
||||||
"Confirm Upload": "Confirm Upload",
|
"Confirm Upload": "Confirm Upload",
|
||||||
"Confirm Edit": "Confirm Edit",
|
"Confirm Edit": "Confirm Edit",
|
||||||
"Create Livestream": "Create Livestream",
|
"Create Livestream": "Create Livestream",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { hot } from 'react-hot-loader/root';
|
import { hot } from 'react-hot-loader/root';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { selectUploadCount } from 'lbryinc';
|
||||||
import { selectGetSyncErrorMessage, selectSyncFatalError } from 'redux/selectors/sync';
|
import { selectGetSyncErrorMessage, selectSyncFatalError } from 'redux/selectors/sync';
|
||||||
import { doFetchAccessToken, doUserSetReferrer } from 'redux/actions/user';
|
import { doFetchAccessToken, doUserSetReferrer } from 'redux/actions/user';
|
||||||
import { selectUser, selectAccessToken, selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUser, selectAccessToken, selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
|
@ -21,7 +22,6 @@ import {
|
||||||
selectActiveChannelClaim,
|
selectActiveChannelClaim,
|
||||||
selectIsReloadRequired,
|
selectIsReloadRequired,
|
||||||
} from 'redux/selectors/app';
|
} from 'redux/selectors/app';
|
||||||
import { selectUploadCount } from 'redux/selectors/publish';
|
|
||||||
import { doGetWalletSyncPreference, doSetLanguage } from 'redux/actions/settings';
|
import { doGetWalletSyncPreference, doSetLanguage } from 'redux/actions/settings';
|
||||||
import { doSyncLoop } from 'redux/actions/sync';
|
import { doSyncLoop } from 'redux/actions/sync';
|
||||||
import {
|
import {
|
||||||
|
|
|
@ -325,7 +325,7 @@ function PublishForm(props: Props) {
|
||||||
submitLabel = __('Uploading...');
|
submitLabel = __('Uploading...');
|
||||||
}
|
}
|
||||||
} else if (previewing) {
|
} else if (previewing) {
|
||||||
submitLabel = <Spinner type="small" />;
|
submitLabel = __('Preparing...');
|
||||||
} else {
|
} else {
|
||||||
if (isStillEditing) {
|
if (isStillEditing) {
|
||||||
submitLabel = __('Save');
|
submitLabel = __('Save');
|
||||||
|
|
|
@ -1,18 +1,13 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
import { selectCurrentUploads, selectUploadCount } from 'lbryinc';
|
||||||
import { doPublishResume, doUpdateUploadRemove } from 'redux/actions/publish';
|
|
||||||
import { selectCurrentUploads, selectUploadCount } from 'redux/selectors/publish';
|
|
||||||
import WebUploadList from './view';
|
import WebUploadList from './view';
|
||||||
|
|
||||||
const select = (state) => ({
|
const select = state => ({
|
||||||
currentUploads: selectCurrentUploads(state),
|
currentUploads: selectCurrentUploads(state),
|
||||||
uploadCount: selectUploadCount(state),
|
uploadCount: selectUploadCount(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = {
|
export default connect(
|
||||||
doPublishResume,
|
select,
|
||||||
doUpdateUploadRemove,
|
null
|
||||||
doOpenModal,
|
)(WebUploadList);
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(select, perform)(WebUploadList);
|
|
||||||
|
|
|
@ -1,155 +1,40 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React, { useState } from 'react';
|
import React from 'react';
|
||||||
import FileSelector from 'component/common/file-selector';
|
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import FileThumbnail from 'component/fileThumbnail';
|
import FileThumbnail from 'component/fileThumbnail';
|
||||||
import * as MODALS from 'constants/modal_types';
|
|
||||||
import { serializeFileObj } from 'util/file';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
uploadItem: FileUploadItem,
|
params: UpdatePublishFormData,
|
||||||
doPublishResume: (any) => void,
|
progress: string,
|
||||||
doUpdateUploadRemove: (any) => void,
|
xhr?: () => void,
|
||||||
doOpenModal: (string, {}) => void,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function WebUploadItem(props: Props) {
|
export default function WebUploadItem(props: Props) {
|
||||||
const { uploadItem, doPublishResume, doUpdateUploadRemove, doOpenModal } = props;
|
const { params, progress, xhr } = props;
|
||||||
const { params, file, fileFingerprint, progress, status, resumable, uploader } = uploadItem;
|
|
||||||
|
|
||||||
const [showFileSelector, setShowFileSelector] = useState(false);
|
|
||||||
|
|
||||||
function handleFileChange(newFile: WebFile, clearName = true) {
|
|
||||||
if (serializeFileObj(newFile) === fileFingerprint) {
|
|
||||||
setShowFileSelector(false);
|
|
||||||
doPublishResume({ ...params, file_path: newFile });
|
|
||||||
} else {
|
|
||||||
doOpenModal(MODALS.CONFIRM, {
|
|
||||||
title: __('Invalid file'),
|
|
||||||
subtitle: __('It appears to be a different or modified file.'),
|
|
||||||
body: <p className="help--warning">{__('Please select the same file from the initial upload.')}</p>,
|
|
||||||
onConfirm: (closeModal) => closeModal(),
|
|
||||||
hideCancel: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleCancel() {
|
|
||||||
doOpenModal(MODALS.CONFIRM, {
|
|
||||||
title: __('Cancel upload'),
|
|
||||||
subtitle: __('Cancel and remove the selected upload?'),
|
|
||||||
body: params.name ? <p className="empty">{`lbry://${params.name}`}</p> : undefined,
|
|
||||||
onConfirm: (closeModal) => {
|
|
||||||
if (uploader) {
|
|
||||||
if (resumable) {
|
|
||||||
// $FlowFixMe - couldn't resolve to TusUploader manually.
|
|
||||||
uploader.abort(true); // TUS
|
|
||||||
} else {
|
|
||||||
uploader.abort(); // XHR
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doUpdateUploadRemove(params);
|
|
||||||
closeModal();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveProgressStr() {
|
|
||||||
if (!uploader) {
|
|
||||||
return __('Stopped.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resumable) {
|
|
||||||
if (status) {
|
|
||||||
switch (status) {
|
|
||||||
case 'retry':
|
|
||||||
return __('Retrying...');
|
|
||||||
case 'error':
|
|
||||||
return __('Failed.');
|
|
||||||
default:
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const progressInt = parseInt(progress);
|
|
||||||
return progressInt === 100 ? __('Processing...') : __('Uploading...');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return __('Uploading...');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRetryButton() {
|
|
||||||
if (!resumable) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uploader) {
|
|
||||||
// Should still be uploading. Don't show.
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
// Refreshed or connection broken.
|
|
||||||
const isFileActive = file instanceof File;
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
label={isFileActive ? __('Resume') : __('Retry')}
|
|
||||||
button="link"
|
|
||||||
onClick={() => {
|
|
||||||
if (isFileActive) {
|
|
||||||
doPublishResume({ ...params, file_path: file });
|
|
||||||
} else {
|
|
||||||
setShowFileSelector(true);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
disabled={showFileSelector}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCancelButton() {
|
|
||||||
return <Button label={__('Cancel')} button="link" onClick={handleCancel} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFileSelector() {
|
|
||||||
return (
|
|
||||||
<div className="claim-preview--padded">
|
|
||||||
<FileSelector
|
|
||||||
label={__('File')}
|
|
||||||
onFileChosen={handleFileChange}
|
|
||||||
// https://stackoverflow.com/questions/19107685/safari-input-type-file-accept-video-ignores-mp4-files
|
|
||||||
accept={'video/mp4,video/x-m4v,video/*,audio/*'}
|
|
||||||
placeholder={__('Select the file to resume upload...')}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getProgressBar() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="claim-upload__progress--label">lbry://{params.name}</div>
|
|
||||||
<div className={'claim-upload__progress--outer card--inline'}>
|
|
||||||
<div className={'claim-upload__progress--inner'} style={{ width: `${progress}%` }}>
|
|
||||||
{resolveProgressStr()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className={'web-upload-item claim-preview claim-preview--padded claim-preview--inactive card--inline'}>
|
<li className={'claim-preview claim-preview--padded claim-preview--inactive card--inline'}>
|
||||||
<FileThumbnail thumbnail={params.thumbnail_url} />
|
<FileThumbnail thumbnail={params.thumbnail_url} />
|
||||||
<div className={'claim-preview-metadata'}>
|
<div className={'claim-preview-metadata'}>
|
||||||
<div className="claim-preview-info">
|
<div className="claim-preview-info">
|
||||||
<div className="claim-preview__title">{params.title}</div>
|
<div className="claim-preview__title">{params.title}</div>
|
||||||
<div className="card__actions--inline">
|
{xhr && (
|
||||||
{getRetryButton()}
|
<div className="card__actions--inline">
|
||||||
{getCancelButton()}
|
<Button
|
||||||
|
button="link"
|
||||||
|
onClick={() => {
|
||||||
|
xhr.abort();
|
||||||
|
}}
|
||||||
|
label={__('Cancel')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<h2>lbry://{params.name}</h2>
|
||||||
|
<div className={'claim-upload__progress--outer card--inline'}>
|
||||||
|
<div className={'claim-upload__progress--inner'} style={{ width: `${progress}%` }}>
|
||||||
|
Uploading...
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{showFileSelector && getFileSelector()}
|
|
||||||
{!showFileSelector && getProgressBar()}
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,16 +3,19 @@ import * as React from 'react';
|
||||||
import Card from 'component/common/card';
|
import Card from 'component/common/card';
|
||||||
import WebUploadItem from './internal/web-upload-item';
|
import WebUploadItem from './internal/web-upload-item';
|
||||||
|
|
||||||
|
export type UploadItem = {
|
||||||
|
progess: string,
|
||||||
|
params: UpdatePublishFormData,
|
||||||
|
xhr?: { abort: () => void },
|
||||||
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
currentUploads: { [key: string]: FileUploadItem },
|
currentUploads: { [key: string]: UploadItem },
|
||||||
uploadCount: number,
|
uploadCount: number,
|
||||||
doPublishResume: (any) => void,
|
|
||||||
doUpdateUploadRemove: (any) => void,
|
|
||||||
doOpenModal: (string, {}) => void,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function WebUploadList(props: Props) {
|
export default function WebUploadList(props: Props) {
|
||||||
const { currentUploads, uploadCount, doPublishResume, doUpdateUploadRemove, doOpenModal } = props;
|
const { currentUploads, uploadCount } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
!!uploadCount && (
|
!!uploadCount && (
|
||||||
|
@ -22,16 +25,8 @@ export default function WebUploadList(props: Props) {
|
||||||
body={
|
body={
|
||||||
<section>
|
<section>
|
||||||
{/* $FlowFixMe */}
|
{/* $FlowFixMe */}
|
||||||
{Object.values(currentUploads).map((uploadItem) => (
|
{Object.values(currentUploads).map(({ progress, params, xhr }) => (
|
||||||
<WebUploadItem
|
<WebUploadItem key={`upload${params.name}`} progress={progress} params={params} xhr={xhr} />
|
||||||
// $FlowFixMe
|
|
||||||
key={`upload${uploadItem.params.name}`}
|
|
||||||
// $FlowFixMe
|
|
||||||
uploadItem={uploadItem}
|
|
||||||
doPublishResume={doPublishResume}
|
|
||||||
doUpdateUploadRemove={doUpdateUploadRemove}
|
|
||||||
doOpenModal={doOpenModal}
|
|
||||||
/>
|
|
||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
}
|
}
|
||||||
|
|
|
@ -331,9 +331,6 @@ export const PUBLISH_FAIL = 'PUBLISH_FAIL';
|
||||||
export const CLEAR_PUBLISH_ERROR = 'CLEAR_PUBLISH_ERROR';
|
export const CLEAR_PUBLISH_ERROR = 'CLEAR_PUBLISH_ERROR';
|
||||||
export const REMOVE_PENDING_PUBLISH = 'REMOVE_PENDING_PUBLISH';
|
export const REMOVE_PENDING_PUBLISH = 'REMOVE_PENDING_PUBLISH';
|
||||||
export const DO_PREPARE_EDIT = 'DO_PREPARE_EDIT';
|
export const DO_PREPARE_EDIT = 'DO_PREPARE_EDIT';
|
||||||
export const UPDATE_UPLOAD_ADD = 'UPDATE_UPLOAD_ADD';
|
|
||||||
export const UPDATE_UPLOAD_PROGRESS = 'UPDATE_UPLOAD_PROGRESS';
|
|
||||||
export const UPDATE_UPLOAD_REMOVE = 'UPDATE_UPLOAD_REMOVE';
|
|
||||||
|
|
||||||
// Media
|
// Media
|
||||||
export const MEDIA_PLAY = 'MEDIA_PLAY';
|
export const MEDIA_PLAY = 'MEDIA_PLAY';
|
||||||
|
@ -494,6 +491,9 @@ export const FETCH_SUB_COUNT_STARTED = 'FETCH_SUB_COUNT_STARTED';
|
||||||
export const FETCH_SUB_COUNT_FAILED = 'FETCH_SUB_COUNT_FAILED';
|
export const FETCH_SUB_COUNT_FAILED = 'FETCH_SUB_COUNT_FAILED';
|
||||||
export const FETCH_SUB_COUNT_COMPLETED = 'FETCH_SUB_COUNT_COMPLETED';
|
export const FETCH_SUB_COUNT_COMPLETED = 'FETCH_SUB_COUNT_COMPLETED';
|
||||||
|
|
||||||
|
// Lbry.tv
|
||||||
|
export const UPDATE_UPLOAD_PROGRESS = 'UPDATE_UPLOAD_PROGRESS';
|
||||||
|
|
||||||
// User
|
// User
|
||||||
export const GENERATE_AUTH_TOKEN_FAILURE = 'GENERATE_AUTH_TOKEN_FAILURE';
|
export const GENERATE_AUTH_TOKEN_FAILURE = 'GENERATE_AUTH_TOKEN_FAILURE';
|
||||||
export const GENERATE_AUTH_TOKEN_STARTED = 'GENERATE_AUTH_TOKEN_STARTED';
|
export const GENERATE_AUTH_TOKEN_STARTED = 'GENERATE_AUTH_TOKEN_STARTED';
|
||||||
|
|
|
@ -35,7 +35,7 @@ import {
|
||||||
doAuthTokenRefresh,
|
doAuthTokenRefresh,
|
||||||
} from 'util/saved-passwords';
|
} from 'util/saved-passwords';
|
||||||
import { X_LBRY_AUTH_TOKEN } from 'constants/token';
|
import { X_LBRY_AUTH_TOKEN } from 'constants/token';
|
||||||
import { LBRY_WEB_API, DEFAULT_LANGUAGE, LBRY_API_URL } from 'config';
|
import { LBRY_WEB_API, DEFAULT_LANGUAGE, LBRY_API_URL, LBRY_WEB_PUBLISH_API } from 'config';
|
||||||
|
|
||||||
// Import 3rd-party styles before ours for the current way we are code-splitting.
|
// Import 3rd-party styles before ours for the current way we are code-splitting.
|
||||||
import 'scss/third-party.scss';
|
import 'scss/third-party.scss';
|
||||||
|
@ -69,6 +69,7 @@ sdkAPIHost = LBRY_WEB_API;
|
||||||
|
|
||||||
export const SDK_API_PATH = `${sdkAPIHost}/api/v1`;
|
export const SDK_API_PATH = `${sdkAPIHost}/api/v1`;
|
||||||
const proxyURL = `${SDK_API_PATH}/proxy`;
|
const proxyURL = `${SDK_API_PATH}/proxy`;
|
||||||
|
const publishURL = LBRY_WEB_PUBLISH_API; // || `${SDK_API_PATH}/proxy`;
|
||||||
|
|
||||||
Lbry.setDaemonConnectionString(proxyURL);
|
Lbry.setDaemonConnectionString(proxyURL);
|
||||||
|
|
||||||
|
@ -78,6 +79,7 @@ Lbry.setOverride(
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
apiPublishCallViaWeb(
|
apiPublishCallViaWeb(
|
||||||
apiCall,
|
apiCall,
|
||||||
|
publishURL,
|
||||||
Lbry.getApiRequestHeaders() && Object.keys(Lbry.getApiRequestHeaders()).includes(X_LBRY_AUTH_TOKEN)
|
Lbry.getApiRequestHeaders() && Object.keys(Lbry.getApiRequestHeaders()).includes(X_LBRY_AUTH_TOKEN)
|
||||||
? Lbry.getApiRequestHeaders()[X_LBRY_AUTH_TOKEN]
|
? Lbry.getApiRequestHeaders()[X_LBRY_AUTH_TOKEN]
|
||||||
: '',
|
: '',
|
||||||
|
|
|
@ -5,9 +5,9 @@ import {
|
||||||
selectMyClaimsPageItemCount,
|
selectMyClaimsPageItemCount,
|
||||||
selectFetchingMyClaimsPageError,
|
selectFetchingMyClaimsPageError,
|
||||||
} from 'redux/selectors/claims';
|
} from 'redux/selectors/claims';
|
||||||
import { selectUploadCount } from 'redux/selectors/publish';
|
|
||||||
import { doFetchClaimListMine, doCheckPendingClaims } from 'redux/actions/claims';
|
import { doFetchClaimListMine, doCheckPendingClaims } from 'redux/actions/claims';
|
||||||
import { doClearPublish } from 'redux/actions/publish';
|
import { doClearPublish } from 'redux/actions/publish';
|
||||||
|
import { selectUploadCount } from 'lbryinc';
|
||||||
import FileListPublished from './view';
|
import FileListPublished from './view';
|
||||||
import { withRouter } from 'react-router';
|
import { withRouter } from 'react-router';
|
||||||
import { MY_CLAIMS_PAGE_SIZE, PAGE_PARAM, PAGE_SIZE_PARAM } from 'constants/claim';
|
import { MY_CLAIMS_PAGE_SIZE, PAGE_PARAM, PAGE_SIZE_PARAM } from 'constants/claim';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
import { connectRouter } from 'connected-react-router';
|
import { connectRouter } from 'connected-react-router';
|
||||||
import { costInfoReducer, blacklistReducer, filteredReducer, statsReducer } from 'lbryinc';
|
import { costInfoReducer, blacklistReducer, filteredReducer, statsReducer, webReducer } from 'lbryinc';
|
||||||
import { claimsReducer } from 'redux/reducers/claims';
|
import { claimsReducer } from 'redux/reducers/claims';
|
||||||
import { fileInfoReducer } from 'redux/reducers/file_info';
|
import { fileInfoReducer } from 'redux/reducers/file_info';
|
||||||
import { walletReducer } from 'redux/reducers/wallet';
|
import { walletReducer } from 'redux/reducers/wallet';
|
||||||
|
@ -50,5 +50,6 @@ export default (history) =>
|
||||||
user: userReducer,
|
user: userReducer,
|
||||||
wallet: walletReducer,
|
wallet: walletReducer,
|
||||||
sync: syncReducer,
|
sync: syncReducer,
|
||||||
|
web: webReducer,
|
||||||
collections: collectionsReducer,
|
collections: collectionsReducer,
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,6 @@ import { batchActions } from 'util/batch-actions';
|
||||||
import { doCheckPendingClaims } from 'redux/actions/claims';
|
import { doCheckPendingClaims } from 'redux/actions/claims';
|
||||||
import {
|
import {
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
selectMyActiveClaims,
|
|
||||||
selectMyClaims,
|
selectMyClaims,
|
||||||
selectMyChannelClaims,
|
selectMyChannelClaims,
|
||||||
// selectMyClaimsWithoutChannels,
|
// selectMyClaimsWithoutChannels,
|
||||||
|
@ -48,147 +47,6 @@ function resolveClaimTypeForAnalytics(claim) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NO_FILE = '---';
|
export const NO_FILE = '---';
|
||||||
|
|
||||||
function resolvePublishPayload(publishData, myClaimForUri, myChannels, preview) {
|
|
||||||
const {
|
|
||||||
name,
|
|
||||||
bid,
|
|
||||||
filePath,
|
|
||||||
description,
|
|
||||||
language,
|
|
||||||
releaseTimeEdited,
|
|
||||||
// license,
|
|
||||||
licenseUrl,
|
|
||||||
useLBRYUploader,
|
|
||||||
licenseType,
|
|
||||||
otherLicenseDescription,
|
|
||||||
thumbnail,
|
|
||||||
channel,
|
|
||||||
title,
|
|
||||||
contentIsFree,
|
|
||||||
fee,
|
|
||||||
// uri,
|
|
||||||
tags,
|
|
||||||
// locations,
|
|
||||||
optimize,
|
|
||||||
isLivestreamPublish,
|
|
||||||
remoteFileUrl,
|
|
||||||
} = publishData;
|
|
||||||
|
|
||||||
// Handle scenario where we have a claim that has the same name as a channel we are publishing with.
|
|
||||||
const myClaimForUriEditing = myClaimForUri && myClaimForUri.name === name ? myClaimForUri : null;
|
|
||||||
|
|
||||||
let publishingLicense;
|
|
||||||
switch (licenseType) {
|
|
||||||
case COPYRIGHT:
|
|
||||||
case OTHER:
|
|
||||||
publishingLicense = otherLicenseDescription;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
publishingLicense = licenseType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the claim id from the channel name, we will use that instead
|
|
||||||
const namedChannelClaim = myChannels ? myChannels.find((myChannel) => myChannel.name === channel) : null;
|
|
||||||
const channelId = namedChannelClaim ? namedChannelClaim.claim_id : '';
|
|
||||||
|
|
||||||
const publishPayload: {
|
|
||||||
name: ?string,
|
|
||||||
bid: string,
|
|
||||||
description?: string,
|
|
||||||
channel_id?: string,
|
|
||||||
file_path?: string,
|
|
||||||
license_url?: string,
|
|
||||||
license?: string,
|
|
||||||
thumbnail_url?: string,
|
|
||||||
release_time?: number,
|
|
||||||
fee_currency?: string,
|
|
||||||
fee_amount?: string,
|
|
||||||
languages?: Array<string>,
|
|
||||||
tags: Array<string>,
|
|
||||||
locations?: Array<any>,
|
|
||||||
blocking: boolean,
|
|
||||||
optimize_file?: boolean,
|
|
||||||
preview?: boolean,
|
|
||||||
remote_url?: string,
|
|
||||||
} = {
|
|
||||||
name,
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
locations: [],
|
|
||||||
bid: creditsToString(bid),
|
|
||||||
languages: [language],
|
|
||||||
tags: tags && tags.map((tag) => tag.name),
|
|
||||||
thumbnail_url: thumbnail,
|
|
||||||
blocking: true,
|
|
||||||
preview: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Temporary solution to keep the same publish flow with the new tags api
|
|
||||||
// Eventually we will allow users to enter their own tags on publish
|
|
||||||
// `nsfw` will probably be removed
|
|
||||||
if (remoteFileUrl) {
|
|
||||||
publishPayload.remote_url = remoteFileUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (publishingLicense) {
|
|
||||||
publishPayload.license = publishingLicense;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (licenseUrl) {
|
|
||||||
publishPayload.license_url = licenseUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thumbnail) {
|
|
||||||
publishPayload.thumbnail_url = thumbnail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useLBRYUploader) {
|
|
||||||
publishPayload.tags.push('lbry-first');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set release time to curret date. On edits, keep original release/transaction time as release_time
|
|
||||||
if (releaseTimeEdited) {
|
|
||||||
publishPayload.release_time = releaseTimeEdited;
|
|
||||||
} else if (myClaimForUriEditing && myClaimForUriEditing.value.release_time) {
|
|
||||||
publishPayload.release_time = Number(myClaimForUri.value.release_time);
|
|
||||||
} else if (myClaimForUriEditing && myClaimForUriEditing.timestamp) {
|
|
||||||
publishPayload.release_time = Number(myClaimForUriEditing.timestamp);
|
|
||||||
} else {
|
|
||||||
publishPayload.release_time = Number(Math.round(Date.now() / 1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channelId) {
|
|
||||||
publishPayload.channel_id = channelId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myClaimForUriEditing && myClaimForUriEditing.value && myClaimForUriEditing.value.locations) {
|
|
||||||
publishPayload.locations = myClaimForUriEditing.value.locations;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!contentIsFree && fee && fee.currency && Number(fee.amount) > 0) {
|
|
||||||
publishPayload.fee_currency = fee.currency;
|
|
||||||
publishPayload.fee_amount = creditsToString(fee.amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optimize) {
|
|
||||||
publishPayload.optimize_file = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only pass file on new uploads, not metadata only edits.
|
|
||||||
// The sdk will figure it out
|
|
||||||
if (filePath && !isLivestreamPublish) {
|
|
||||||
publishPayload.file_path = filePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preview) {
|
|
||||||
publishPayload.preview = true;
|
|
||||||
publishPayload.optimize_file = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return publishPayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const doPublishDesktop = (filePath: string, preview?: boolean) => (dispatch: Dispatch, getState: () => {}) => {
|
export const doPublishDesktop = (filePath: string, preview?: boolean) => (dispatch: Dispatch, getState: () => {}) => {
|
||||||
const publishPreview = (previewResponse) => {
|
const publishPreview = (previewResponse) => {
|
||||||
dispatch(
|
dispatch(
|
||||||
|
@ -290,62 +148,6 @@ export const doPublishDesktop = (filePath: string, preview?: boolean) => (dispat
|
||||||
dispatch(doPublish(publishSuccess, publishFail));
|
dispatch(doPublish(publishSuccess, publishFail));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const doPublishResume = (publishPayload: any) => (dispatch: Dispatch, getState: () => {}) => {
|
|
||||||
const publishSuccess = (successResponse, lbryFirstError) => {
|
|
||||||
const state = getState();
|
|
||||||
const myClaimIds: Set<string> = selectMyActiveClaims(state);
|
|
||||||
|
|
||||||
const pendingClaim = successResponse.outputs[0];
|
|
||||||
const { permanent_url: url } = pendingClaim;
|
|
||||||
|
|
||||||
analytics.apiLogPublish(pendingClaim);
|
|
||||||
|
|
||||||
// We have to fake a temp claim until the new pending one is returned by claim_list_mine
|
|
||||||
// We can't rely on claim_list_mine because there might be some delay before the new claims are returned
|
|
||||||
// Doing this allows us to show the pending claim immediately, it will get overwritten by the real one
|
|
||||||
const isEdit = myClaimIds.has(pendingClaim.claim_id);
|
|
||||||
|
|
||||||
const actions = [];
|
|
||||||
|
|
||||||
actions.push({
|
|
||||||
type: ACTIONS.PUBLISH_SUCCESS,
|
|
||||||
data: {
|
|
||||||
type: resolveClaimTypeForAnalytics(pendingClaim),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
actions.push({
|
|
||||||
type: ACTIONS.UPDATE_PENDING_CLAIMS,
|
|
||||||
data: {
|
|
||||||
claims: [pendingClaim],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
dispatch(batchActions(...actions));
|
|
||||||
|
|
||||||
dispatch(
|
|
||||||
doOpenModal(MODALS.PUBLISH, {
|
|
||||||
uri: url,
|
|
||||||
isEdit,
|
|
||||||
lbryFirstError,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
dispatch(doCheckPendingClaims());
|
|
||||||
};
|
|
||||||
|
|
||||||
const publishFail = (error) => {
|
|
||||||
const actions = [];
|
|
||||||
actions.push({
|
|
||||||
type: ACTIONS.PUBLISH_FAIL,
|
|
||||||
});
|
|
||||||
actions.push(doError(error.message));
|
|
||||||
dispatch(batchActions(...actions));
|
|
||||||
};
|
|
||||||
|
|
||||||
dispatch(doPublish(publishSuccess, publishFail, false, publishPayload));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const doResetThumbnailStatus = () => (dispatch: Dispatch) => {
|
export const doResetThumbnailStatus = () => (dispatch: Dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.UPDATE_PUBLISH_FORM,
|
type: ACTIONS.UPDATE_PUBLISH_FORM,
|
||||||
|
@ -571,7 +373,7 @@ export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileLis
|
||||||
dispatch({ type: ACTIONS.DO_PREPARE_EDIT, data: publishData });
|
dispatch({ type: ACTIONS.DO_PREPARE_EDIT, data: publishData });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const doPublish = (success: Function, fail: Function, preview: Function, payload: any) => (
|
export const doPublish = (success: Function, fail: Function, preview: Function) => (
|
||||||
dispatch: Dispatch,
|
dispatch: Dispatch,
|
||||||
getState: () => {}
|
getState: () => {}
|
||||||
) => {
|
) => {
|
||||||
|
@ -586,9 +388,139 @@ export const doPublish = (success: Function, fail: Function, preview: Function,
|
||||||
// get redux publish form
|
// get redux publish form
|
||||||
const publishData = selectPublishFormValues(state);
|
const publishData = selectPublishFormValues(state);
|
||||||
|
|
||||||
const publishPayload = payload || resolvePublishPayload(publishData, myClaimForUri, myChannels, preview);
|
// destructure the data values
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
bid,
|
||||||
|
filePath,
|
||||||
|
description,
|
||||||
|
language,
|
||||||
|
releaseTimeEdited,
|
||||||
|
// license,
|
||||||
|
licenseUrl,
|
||||||
|
useLBRYUploader,
|
||||||
|
licenseType,
|
||||||
|
otherLicenseDescription,
|
||||||
|
thumbnail,
|
||||||
|
channel,
|
||||||
|
title,
|
||||||
|
contentIsFree,
|
||||||
|
fee,
|
||||||
|
// uri,
|
||||||
|
tags,
|
||||||
|
// locations,
|
||||||
|
optimize,
|
||||||
|
isLivestreamPublish,
|
||||||
|
remoteFileUrl,
|
||||||
|
} = publishData;
|
||||||
|
|
||||||
|
// Handle scenario where we have a claim that has the same name as a channel we are publishing with.
|
||||||
|
const myClaimForUriEditing = myClaimForUri && myClaimForUri.name === name ? myClaimForUri : null;
|
||||||
|
|
||||||
|
let publishingLicense;
|
||||||
|
switch (licenseType) {
|
||||||
|
case COPYRIGHT:
|
||||||
|
case OTHER:
|
||||||
|
publishingLicense = otherLicenseDescription;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
publishingLicense = licenseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the claim id from the channel name, we will use that instead
|
||||||
|
const namedChannelClaim = myChannels ? myChannels.find((myChannel) => myChannel.name === channel) : null;
|
||||||
|
const channelId = namedChannelClaim ? namedChannelClaim.claim_id : '';
|
||||||
|
|
||||||
|
const publishPayload: {
|
||||||
|
name: ?string,
|
||||||
|
bid: string,
|
||||||
|
description?: string,
|
||||||
|
channel_id?: string,
|
||||||
|
file_path?: string,
|
||||||
|
license_url?: string,
|
||||||
|
license?: string,
|
||||||
|
thumbnail_url?: string,
|
||||||
|
release_time?: number,
|
||||||
|
fee_currency?: string,
|
||||||
|
fee_amount?: string,
|
||||||
|
languages?: Array<string>,
|
||||||
|
tags: Array<string>,
|
||||||
|
locations?: Array<any>,
|
||||||
|
blocking: boolean,
|
||||||
|
optimize_file?: boolean,
|
||||||
|
preview?: boolean,
|
||||||
|
remote_url?: string,
|
||||||
|
} = {
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
locations: [],
|
||||||
|
bid: creditsToString(bid),
|
||||||
|
languages: [language],
|
||||||
|
tags: tags && tags.map((tag) => tag.name),
|
||||||
|
thumbnail_url: thumbnail,
|
||||||
|
blocking: true,
|
||||||
|
preview: false,
|
||||||
|
};
|
||||||
|
// Temporary solution to keep the same publish flow with the new tags api
|
||||||
|
// Eventually we will allow users to enter their own tags on publish
|
||||||
|
// `nsfw` will probably be removed
|
||||||
|
if (remoteFileUrl) {
|
||||||
|
publishPayload.remote_url = remoteFileUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (publishingLicense) {
|
||||||
|
publishPayload.license = publishingLicense;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (licenseUrl) {
|
||||||
|
publishPayload.license_url = licenseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thumbnail) {
|
||||||
|
publishPayload.thumbnail_url = thumbnail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useLBRYUploader) {
|
||||||
|
publishPayload.tags.push('lbry-first');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set release time to curret date. On edits, keep original release/transaction time as release_time
|
||||||
|
if (releaseTimeEdited) {
|
||||||
|
publishPayload.release_time = releaseTimeEdited;
|
||||||
|
} else if (myClaimForUriEditing && myClaimForUriEditing.value.release_time) {
|
||||||
|
publishPayload.release_time = Number(myClaimForUri.value.release_time);
|
||||||
|
} else if (myClaimForUriEditing && myClaimForUriEditing.timestamp) {
|
||||||
|
publishPayload.release_time = Number(myClaimForUriEditing.timestamp);
|
||||||
|
} else {
|
||||||
|
publishPayload.release_time = Number(Math.round(Date.now() / 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channelId) {
|
||||||
|
publishPayload.channel_id = channelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myClaimForUriEditing && myClaimForUriEditing.value && myClaimForUriEditing.value.locations) {
|
||||||
|
publishPayload.locations = myClaimForUriEditing.value.locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!contentIsFree && fee && fee.currency && Number(fee.amount) > 0) {
|
||||||
|
publishPayload.fee_currency = fee.currency;
|
||||||
|
publishPayload.fee_amount = creditsToString(fee.amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optimize) {
|
||||||
|
publishPayload.optimize_file = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only pass file on new uploads, not metadata only edits.
|
||||||
|
// The sdk will figure it out
|
||||||
|
if (filePath && !isLivestreamPublish) publishPayload.file_path = filePath;
|
||||||
|
|
||||||
if (preview) {
|
if (preview) {
|
||||||
|
publishPayload.preview = true;
|
||||||
|
publishPayload.optimize_file = false;
|
||||||
|
|
||||||
return Lbry.publish(publishPayload).then((previewResponse: PublishResponse) => {
|
return Lbry.publish(publishPayload).then((previewResponse: PublishResponse) => {
|
||||||
return preview(previewResponse);
|
return preview(previewResponse);
|
||||||
}, fail);
|
}, fail);
|
||||||
|
@ -688,35 +620,3 @@ export const doCheckReflectingFiles = () => (dispatch: Dispatch, getState: GetSt
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export function doUpdateUploadAdd(
|
|
||||||
file: File | string,
|
|
||||||
params: { [key: string]: any },
|
|
||||||
uploader: TusUploader | XMLHttpRequest
|
|
||||||
) {
|
|
||||||
return (dispatch: Dispatch, getState: GetState) => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.UPDATE_UPLOAD_ADD,
|
|
||||||
data: { file, params, uploader },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export const doUpdateUploadProgress = (props: {
|
|
||||||
params: { [key: string]: any },
|
|
||||||
progress?: string,
|
|
||||||
status?: string,
|
|
||||||
}) => (dispatch: Dispatch) =>
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.UPDATE_UPLOAD_PROGRESS,
|
|
||||||
data: props,
|
|
||||||
});
|
|
||||||
|
|
||||||
export function doUpdateUploadRemove(params: { [key: string]: any }) {
|
|
||||||
return (dispatch: Dispatch, getState: GetState) => {
|
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.UPDATE_UPLOAD_REMOVE,
|
|
||||||
data: { params },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { handleActions } from 'util/redux-utils';
|
import { handleActions } from 'util/redux-utils';
|
||||||
import { buildURI } from 'util/lbryURI';
|
import { buildURI } from 'util/lbryURI';
|
||||||
import { serializeFileObj } from 'util/file';
|
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import * as THUMBNAIL_STATUSES from 'constants/thumbnail_upload_statuses';
|
import * as THUMBNAIL_STATUSES from 'constants/thumbnail_upload_statuses';
|
||||||
import { CHANNEL_ANONYMOUS } from 'constants/claim';
|
import { CHANNEL_ANONYMOUS } from 'constants/claim';
|
||||||
|
|
||||||
const getKeyFromParam = (params) => `${params.name}#${params.channel || 'anonymous'}`;
|
|
||||||
|
|
||||||
type PublishState = {
|
type PublishState = {
|
||||||
editingURI: ?string,
|
editingURI: ?string,
|
||||||
fileText: ?string,
|
fileText: ?string,
|
||||||
|
@ -41,7 +38,6 @@ type PublishState = {
|
||||||
tags: Array<string>,
|
tags: Array<string>,
|
||||||
optimize: boolean,
|
optimize: boolean,
|
||||||
useLBRYUploader: boolean,
|
useLBRYUploader: boolean,
|
||||||
currentUploads: { [key: string]: FileUploadItem },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultState: PublishState = {
|
const defaultState: PublishState = {
|
||||||
|
@ -82,7 +78,6 @@ const defaultState: PublishState = {
|
||||||
publishError: undefined,
|
publishError: undefined,
|
||||||
optimize: false,
|
optimize: false,
|
||||||
useLBRYUploader: false,
|
useLBRYUploader: false,
|
||||||
currentUploads: {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const publishReducer = handleActions(
|
export const publishReducer = handleActions(
|
||||||
|
@ -101,7 +96,6 @@ export const publishReducer = handleActions(
|
||||||
bid: state.bid,
|
bid: state.bid,
|
||||||
optimize: state.optimize,
|
optimize: state.optimize,
|
||||||
language: state.language,
|
language: state.language,
|
||||||
currentUploads: state.currentUploads,
|
|
||||||
}),
|
}),
|
||||||
[ACTIONS.PUBLISH_START]: (state: PublishState): PublishState => ({
|
[ACTIONS.PUBLISH_START]: (state: PublishState): PublishState => ({
|
||||||
...state,
|
...state,
|
||||||
|
@ -133,76 +127,8 @@ export const publishReducer = handleActions(
|
||||||
...publishData,
|
...publishData,
|
||||||
editingURI: uri,
|
editingURI: uri,
|
||||||
uri: shortUri,
|
uri: shortUri,
|
||||||
currentUploads: state.currentUploads,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[ACTIONS.UPDATE_UPLOAD_ADD]: (state: PublishState, action) => {
|
|
||||||
const { file, params, uploader } = action.data;
|
|
||||||
const key = getKeyFromParam(params);
|
|
||||||
const currentUploads = Object.assign({}, state.currentUploads);
|
|
||||||
|
|
||||||
currentUploads[key] = {
|
|
||||||
file,
|
|
||||||
fileFingerprint: file ? serializeFileObj(file) : undefined, // TODO: get hash instead?
|
|
||||||
progress: '0',
|
|
||||||
params,
|
|
||||||
uploader,
|
|
||||||
resumable: !(uploader instanceof XMLHttpRequest),
|
|
||||||
};
|
|
||||||
|
|
||||||
return { ...state, currentUploads };
|
|
||||||
},
|
|
||||||
[ACTIONS.UPDATE_UPLOAD_PROGRESS]: (state: PublishState, action) => {
|
|
||||||
const { params, progress, status } = action.data;
|
|
||||||
const key = getKeyFromParam(params);
|
|
||||||
const currentUploads = Object.assign({}, state.currentUploads);
|
|
||||||
|
|
||||||
if (!currentUploads[key]) {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (progress) {
|
|
||||||
currentUploads[key].progress = progress;
|
|
||||||
delete currentUploads[key].status;
|
|
||||||
} else if (status) {
|
|
||||||
currentUploads[key].status = status;
|
|
||||||
if (status === 'error') {
|
|
||||||
delete currentUploads[key].uploader;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { ...state, currentUploads };
|
|
||||||
},
|
|
||||||
[ACTIONS.UPDATE_UPLOAD_REMOVE]: (state: PublishState, action) => {
|
|
||||||
const { params } = action.data;
|
|
||||||
const key = getKeyFromParam(params);
|
|
||||||
const currentUploads = Object.assign({}, state.currentUploads);
|
|
||||||
|
|
||||||
delete currentUploads[key];
|
|
||||||
|
|
||||||
return { ...state, currentUploads };
|
|
||||||
},
|
|
||||||
[ACTIONS.REHYDRATE]: (state: PublishState, action) => {
|
|
||||||
if (action && action.payload && action.payload.publish) {
|
|
||||||
const newPublish = { ...action.payload.publish };
|
|
||||||
|
|
||||||
// Cleanup for 'publish::currentUploads'
|
|
||||||
if (newPublish.currentUploads) {
|
|
||||||
Object.keys(newPublish.currentUploads).forEach((key) => {
|
|
||||||
const params = newPublish.currentUploads[key].params;
|
|
||||||
if (!params || Object.keys(params).length === 0) {
|
|
||||||
delete newPublish.currentUploads[key];
|
|
||||||
} else {
|
|
||||||
delete newPublish.currentUploads[key].uploader;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return newPublish;
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
defaultState
|
defaultState
|
||||||
);
|
);
|
||||||
|
|
|
@ -119,10 +119,3 @@ export const selectTakeOverAmount = createSelector(
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectCurrentUploads = (state) => selectState(state).currentUploads;
|
|
||||||
|
|
||||||
export const selectUploadCount = createSelector(
|
|
||||||
selectCurrentUploads,
|
|
||||||
(currentUploads) => currentUploads && Object.keys(currentUploads).length
|
|
||||||
);
|
|
||||||
|
|
|
@ -363,11 +363,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.claim-upload__progress--label {
|
|
||||||
font-size: var(--font-small);
|
|
||||||
color: var(--color-text-subtitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
.claim-upload__progress--outer {
|
.claim-upload__progress--outer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -862,17 +857,3 @@
|
||||||
margin-top: var(--spacing-s);
|
margin-top: var(--spacing-s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.web-upload-item.claim-preview {
|
|
||||||
@media (max-width: $breakpoint-small) {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
.media__thumb {
|
|
||||||
margin-bottom: var(--spacing-s);
|
|
||||||
}
|
|
||||||
|
|
||||||
.claim-preview-metadata {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
export function serializeFileObj(file: File) {
|
|
||||||
return `${file.name}#${file.type}#${file.size}`;
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
// https://api.na-backend.odysee.com/api/v1/proxy currently expects publish to
|
|
||||||
// consist of a multipart/form-data POST request with:
|
|
||||||
// - 'file' binary
|
|
||||||
// - 'json_payload' publish params to be passed to the server's sdk.
|
|
||||||
|
|
||||||
import { X_LBRY_AUTH_TOKEN } from '../../ui/constants/token';
|
|
||||||
import { doUpdateUploadAdd, doUpdateUploadProgress, doUpdateUploadRemove } from '../../ui/redux/actions/publish';
|
|
||||||
import { LBRY_WEB_PUBLISH_API } from 'config';
|
|
||||||
|
|
||||||
const ENDPOINT = LBRY_WEB_PUBLISH_API;
|
|
||||||
const ENDPOINT_METHOD = 'publish';
|
|
||||||
|
|
||||||
export function makeUploadRequest(
|
|
||||||
token: string,
|
|
||||||
params: FileUploadSdkParams,
|
|
||||||
file: File | string,
|
|
||||||
isPreview?: boolean
|
|
||||||
) {
|
|
||||||
const { remote_url: remoteUrl } = params;
|
|
||||||
|
|
||||||
const body = new FormData();
|
|
||||||
|
|
||||||
if (file) {
|
|
||||||
body.append('file', file);
|
|
||||||
delete params['remote_url'];
|
|
||||||
} else if (remoteUrl) {
|
|
||||||
body.append('remote_url', remoteUrl);
|
|
||||||
delete params['remote_url'];
|
|
||||||
}
|
|
||||||
|
|
||||||
const jsonPayload = JSON.stringify({
|
|
||||||
jsonrpc: '2.0',
|
|
||||||
method: ENDPOINT_METHOD,
|
|
||||||
params,
|
|
||||||
id: new Date().getTime(),
|
|
||||||
});
|
|
||||||
|
|
||||||
// no fileData? do the livestream remote publish
|
|
||||||
body.append('json_payload', jsonPayload);
|
|
||||||
|
|
||||||
return new Promise<any>((resolve, reject) => {
|
|
||||||
let xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('POST', ENDPOINT);
|
|
||||||
xhr.setRequestHeader(X_LBRY_AUTH_TOKEN, token);
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.upload.onprogress = (e) => {
|
|
||||||
const percentage = ((e.loaded / e.total) * 100).toFixed(2);
|
|
||||||
window.store.dispatch(doUpdateUploadProgress({ params, progress: percentage }));
|
|
||||||
};
|
|
||||||
xhr.onload = () => {
|
|
||||||
window.store.dispatch(doUpdateUploadRemove(params));
|
|
||||||
resolve(xhr);
|
|
||||||
};
|
|
||||||
xhr.onerror = () => {
|
|
||||||
window.store.dispatch(doUpdateUploadProgress({ params, status: 'error' }));
|
|
||||||
reject(new Error(__('There was a problem with your upload. Please try again.')));
|
|
||||||
};
|
|
||||||
xhr.onabort = () => {
|
|
||||||
window.store.dispatch(doUpdateUploadRemove(params));
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!isPreview) {
|
|
||||||
window.store.dispatch(doUpdateUploadAdd(file, params, xhr));
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.send(body);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
// @flow
|
|
||||||
import * as tus from 'tus-js-client';
|
|
||||||
import { X_LBRY_AUTH_TOKEN } from '../../ui/constants/token';
|
|
||||||
import { doUpdateUploadAdd, doUpdateUploadProgress, doUpdateUploadRemove } from '../../ui/redux/actions/publish';
|
|
||||||
import { LBRY_WEB_PUBLISH_API_V2 } from 'config';
|
|
||||||
|
|
||||||
const RESUMABLE_ENDPOINT = LBRY_WEB_PUBLISH_API_V2;
|
|
||||||
const RESUMABLE_ENDPOINT_METHOD = 'publish';
|
|
||||||
const UPLOAD_CHUNK_SIZE_BYTE = 100000000;
|
|
||||||
|
|
||||||
export function makeResumableUploadRequest(
|
|
||||||
token: string,
|
|
||||||
params: FileUploadSdkParams,
|
|
||||||
file: File | string,
|
|
||||||
isPreview?: boolean
|
|
||||||
) {
|
|
||||||
return new Promise<any>((resolve, reject) => {
|
|
||||||
if (!RESUMABLE_ENDPOINT) {
|
|
||||||
reject(new Error('Publish: endpoint undefined'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// @if NODE_ENV!='production'
|
|
||||||
if (params.remote_url) {
|
|
||||||
reject(new Error('Publish: v2 does not support remote_url'));
|
|
||||||
}
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
const jsonPayload = JSON.stringify({
|
|
||||||
jsonrpc: '2.0',
|
|
||||||
method: RESUMABLE_ENDPOINT_METHOD,
|
|
||||||
params,
|
|
||||||
id: new Date().getTime(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const uploader = new tus.Upload(file, {
|
|
||||||
endpoint: RESUMABLE_ENDPOINT,
|
|
||||||
chunkSize: UPLOAD_CHUNK_SIZE_BYTE,
|
|
||||||
retryDelays: [0, 3000, 3000],
|
|
||||||
parallelUploads: 1,
|
|
||||||
removeFingerprintOnSuccess: true,
|
|
||||||
headers: { [X_LBRY_AUTH_TOKEN]: token },
|
|
||||||
metadata: {
|
|
||||||
filename: file instanceof File ? file.name : file,
|
|
||||||
filetype: file instanceof File ? file.type : undefined,
|
|
||||||
},
|
|
||||||
onShouldRetry: (err, retryAttempt, options) => {
|
|
||||||
window.store.dispatch(doUpdateUploadProgress({ params, status: 'retry' }));
|
|
||||||
const FORBIDDEN_ERROR = 403;
|
|
||||||
const status = err.originalResponse ? err.originalResponse.getStatus() : 0;
|
|
||||||
return status !== FORBIDDEN_ERROR;
|
|
||||||
},
|
|
||||||
onError: (error) => {
|
|
||||||
window.store.dispatch(doUpdateUploadProgress({ params, status: 'error' }));
|
|
||||||
reject(new Error(error));
|
|
||||||
},
|
|
||||||
onProgress: (bytesUploaded, bytesTotal) => {
|
|
||||||
const percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2);
|
|
||||||
window.store.dispatch(doUpdateUploadProgress({ params, progress: percentage }));
|
|
||||||
},
|
|
||||||
onSuccess: () => {
|
|
||||||
// Notify lbrynet server
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('POST', `${uploader.url}/notify`);
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
|
||||||
xhr.setRequestHeader('Tus-Resumable', '1.0.0');
|
|
||||||
xhr.setRequestHeader(X_LBRY_AUTH_TOKEN, token);
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.onload = () => {
|
|
||||||
window.store.dispatch(doUpdateUploadRemove(params));
|
|
||||||
resolve(xhr);
|
|
||||||
};
|
|
||||||
xhr.onerror = () => {
|
|
||||||
reject(new Error(__('There was a problem with your upload. Please try again.')));
|
|
||||||
};
|
|
||||||
xhr.onabort = () => {
|
|
||||||
window.store.dispatch(doUpdateUploadRemove(params));
|
|
||||||
};
|
|
||||||
|
|
||||||
xhr.send(jsonPayload);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
uploader
|
|
||||||
.findPreviousUploads()
|
|
||||||
.then((previousUploads) => {
|
|
||||||
if (previousUploads.length > 0) {
|
|
||||||
uploader.resumeFromPreviousUpload(previousUploads[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isPreview) {
|
|
||||||
window.store.dispatch(doUpdateUploadAdd(file, params, uploader));
|
|
||||||
}
|
|
||||||
|
|
||||||
uploader.start();
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
reject(new Error(__('Failed to initiate upload (%err%)', { err })));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,16 +1,22 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as tus from 'tus-js-client';
|
/*
|
||||||
import { makeUploadRequest } from './publish-v1';
|
https://api.na-backend.odysee.com/api/v1/proxy currently expects publish to consist
|
||||||
import { makeResumableUploadRequest } from './publish-v2';
|
of a multipart/form-data POST request with:
|
||||||
|
- 'file' binary
|
||||||
|
- 'json_payload' collection of publish params to be passed to the server's sdk.
|
||||||
|
*/
|
||||||
|
import { X_LBRY_AUTH_TOKEN } from '../../ui/constants/token';
|
||||||
|
import { doUpdateUploadProgress } from 'lbryinc';
|
||||||
|
|
||||||
// A modified version of Lbry.apiCall that allows
|
// A modified version of Lbry.apiCall that allows
|
||||||
// to perform calling methods at arbitrary urls
|
// to perform calling methods at arbitrary urls
|
||||||
// and pass form file fields
|
// and pass form file fields
|
||||||
export default function apiPublishCallViaWeb(
|
export default function apiPublishCallViaWeb(
|
||||||
apiCall: (any, any, any, any) => any,
|
apiCall: (any, any, any, any) => any,
|
||||||
|
connectionString: string,
|
||||||
token: string,
|
token: string,
|
||||||
method: string,
|
method: string,
|
||||||
params: FileUploadSdkParams,
|
params: { file_path: string, preview: boolean, remote_url?: string }, // new param for remoteUrl
|
||||||
resolve: Function,
|
resolve: Function,
|
||||||
reject: Function
|
reject: Function
|
||||||
) {
|
) {
|
||||||
|
@ -20,6 +26,7 @@ export default function apiPublishCallViaWeb(
|
||||||
return apiCall(method, params, resolve, reject);
|
return apiCall(method, params, resolve, reject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const counter = new Date().getTime();
|
||||||
let fileField = filePath;
|
let fileField = filePath;
|
||||||
|
|
||||||
if (preview) {
|
if (preview) {
|
||||||
|
@ -30,16 +37,53 @@ export default function apiPublishCallViaWeb(
|
||||||
|
|
||||||
// Putting a dummy value here, the server is going to process the POSTed file
|
// Putting a dummy value here, the server is going to process the POSTed file
|
||||||
// and set the file_path itself
|
// and set the file_path itself
|
||||||
|
|
||||||
|
const body = new FormData();
|
||||||
if (fileField) {
|
if (fileField) {
|
||||||
|
body.append('file', fileField);
|
||||||
params.file_path = '__POST_FILE__';
|
params.file_path = '__POST_FILE__';
|
||||||
|
delete params['remote_url'];
|
||||||
|
} else if (remoteUrl) {
|
||||||
|
body.append('remote_url', remoteUrl);
|
||||||
|
delete params['remote_url'];
|
||||||
}
|
}
|
||||||
|
|
||||||
const useV1 = remoteUrl || preview || !tus.isSupported;
|
const jsonPayload = JSON.stringify({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
id: counter,
|
||||||
|
});
|
||||||
|
// no fileData? do the livestream remote publish
|
||||||
|
body.append('json_payload', jsonPayload);
|
||||||
|
|
||||||
// Note: both function signature (params) should match.
|
function makeRequest(connectionString, method, token, body, params) {
|
||||||
const makeRequest = useV1 ? makeUploadRequest : makeResumableUploadRequest;
|
return new Promise((resolve, reject) => {
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.open(method, connectionString);
|
||||||
|
xhr.setRequestHeader(X_LBRY_AUTH_TOKEN, token);
|
||||||
|
xhr.responseType = 'json';
|
||||||
|
xhr.upload.onprogress = (e) => {
|
||||||
|
let percentComplete = Math.ceil((e.loaded / e.total) * 100);
|
||||||
|
window.store.dispatch(doUpdateUploadProgress(percentComplete, params, xhr));
|
||||||
|
};
|
||||||
|
xhr.onload = () => {
|
||||||
|
window.store.dispatch(doUpdateUploadProgress(undefined, params));
|
||||||
|
resolve(xhr);
|
||||||
|
};
|
||||||
|
xhr.onerror = () => {
|
||||||
|
window.store.dispatch(doUpdateUploadProgress(undefined, params));
|
||||||
|
reject(new Error(__('There was a problem with your upload. Please try again.')));
|
||||||
|
};
|
||||||
|
|
||||||
return makeRequest(token, params, fileField, preview)
|
xhr.onabort = () => {
|
||||||
|
window.store.dispatch(doUpdateUploadProgress(undefined, params));
|
||||||
|
};
|
||||||
|
xhr.send(body);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeRequest(connectionString, 'POST', token, body, params)
|
||||||
.then((xhr) => {
|
.then((xhr) => {
|
||||||
let error;
|
let error;
|
||||||
if (xhr && xhr.response) {
|
if (xhr && xhr.response) {
|
||||||
|
|
96
yarn.lock
96
yarn.lock
|
@ -3869,11 +3869,6 @@ buffer-fill@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
|
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
|
||||||
|
|
||||||
buffer-from@^0.1.1:
|
|
||||||
version "0.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-0.1.2.tgz#15f4b9bcef012044df31142c14333caf6e0260d0"
|
|
||||||
integrity sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==
|
|
||||||
|
|
||||||
buffer-from@^1.0.0:
|
buffer-from@^1.0.0:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||||
|
@ -4639,14 +4634,6 @@ colors@~1.1.2:
|
||||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
|
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
|
||||||
integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM=
|
integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM=
|
||||||
|
|
||||||
combine-errors@^3.0.3:
|
|
||||||
version "3.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/combine-errors/-/combine-errors-3.0.3.tgz#f4df6740083e5703a3181110c2b10551f003da86"
|
|
||||||
integrity sha1-9N9nQAg+VwOjGBEQwrEFUfAD2oY=
|
|
||||||
dependencies:
|
|
||||||
custom-error-instance "2.1.1"
|
|
||||||
lodash.uniqby "4.5.0"
|
|
||||||
|
|
||||||
combined-stream@^1.0.6, combined-stream@~1.0.5, combined-stream@~1.0.6:
|
combined-stream@^1.0.6, combined-stream@~1.0.5, combined-stream@~1.0.6:
|
||||||
version "1.0.8"
|
version "1.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||||
|
@ -5350,11 +5337,6 @@ currently-unhandled@^0.4.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
array-find-index "^1.0.1"
|
array-find-index "^1.0.1"
|
||||||
|
|
||||||
custom-error-instance@2.1.1:
|
|
||||||
version "2.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/custom-error-instance/-/custom-error-instance-2.1.1.tgz#3cf6391487a6629a6247eb0ca0ce00081b7e361a"
|
|
||||||
integrity sha1-PPY5FIemYppiR+sMoM4ACBt+Nho=
|
|
||||||
|
|
||||||
cyclist@^1.0.1:
|
cyclist@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
||||||
|
@ -9842,7 +9824,7 @@ jest@20.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
jest-cli "^20.0.4"
|
jest-cli "^20.0.4"
|
||||||
|
|
||||||
js-base64@^2.1.9, js-base64@^2.6.1:
|
js-base64@^2.1.9:
|
||||||
version "2.6.4"
|
version "2.6.4"
|
||||||
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
|
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
|
||||||
integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
|
integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
|
||||||
|
@ -10393,48 +10375,11 @@ lodash-es@^4.17.14, lodash-es@^4.2.1:
|
||||||
version "4.17.15"
|
version "4.17.15"
|
||||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
|
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
|
||||||
|
|
||||||
lodash._baseiteratee@~4.7.0:
|
|
||||||
version "4.7.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash._baseiteratee/-/lodash._baseiteratee-4.7.0.tgz#34a9b5543572727c3db2e78edae3c0e9e66bd102"
|
|
||||||
integrity sha1-NKm1VDVycnw9sueO2uPA6eZr0QI=
|
|
||||||
dependencies:
|
|
||||||
lodash._stringtopath "~4.8.0"
|
|
||||||
|
|
||||||
lodash._basetostring@~4.12.0:
|
|
||||||
version "4.12.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz#9327c9dc5158866b7fa4b9d42f4638e5766dd9df"
|
|
||||||
integrity sha1-kyfJ3FFYhmt/pLnUL0Y45XZt2d8=
|
|
||||||
|
|
||||||
lodash._baseuniq@~4.6.0:
|
|
||||||
version "4.6.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
|
|
||||||
integrity sha1-DrtE5FaBSveQXGIS+iybLVG4Qeg=
|
|
||||||
dependencies:
|
|
||||||
lodash._createset "~4.0.0"
|
|
||||||
lodash._root "~3.0.0"
|
|
||||||
|
|
||||||
lodash._createset@~4.0.0:
|
|
||||||
version "4.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
|
|
||||||
integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=
|
|
||||||
|
|
||||||
lodash._reinterpolate@^3.0.0:
|
lodash._reinterpolate@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
|
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
|
||||||
integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
|
integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
|
||||||
|
|
||||||
lodash._root@~3.0.0:
|
|
||||||
version "3.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
|
|
||||||
integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=
|
|
||||||
|
|
||||||
lodash._stringtopath@~4.8.0:
|
|
||||||
version "4.8.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash._stringtopath/-/lodash._stringtopath-4.8.0.tgz#941bcf0e64266e5fc1d66fed0a6959544c576824"
|
|
||||||
integrity sha1-lBvPDmQmbl/B1m/tCmlZVExXaCQ=
|
|
||||||
dependencies:
|
|
||||||
lodash._basetostring "~4.12.0"
|
|
||||||
|
|
||||||
lodash.camelcase@^4.3.0:
|
lodash.camelcase@^4.3.0:
|
||||||
version "4.3.0"
|
version "4.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
|
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
|
||||||
|
@ -10504,11 +10449,6 @@ lodash.templatesettings@^4.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
lodash._reinterpolate "^3.0.0"
|
lodash._reinterpolate "^3.0.0"
|
||||||
|
|
||||||
lodash.throttle@^4.1.1:
|
|
||||||
version "4.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
|
||||||
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
|
|
||||||
|
|
||||||
lodash.toarray@^4.4.0:
|
lodash.toarray@^4.4.0:
|
||||||
version "4.4.0"
|
version "4.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
|
resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
|
||||||
|
@ -10517,14 +10457,6 @@ lodash.uniq@^4.5.0:
|
||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||||
|
|
||||||
lodash.uniqby@4.5.0:
|
|
||||||
version "4.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.5.0.tgz#a3a17bbf62eeb6240f491846e97c1c4e2a5e1e21"
|
|
||||||
integrity sha1-o6F7v2LutiQPSRhG6XwcTipeHiE=
|
|
||||||
dependencies:
|
|
||||||
lodash._baseiteratee "~4.7.0"
|
|
||||||
lodash._baseuniq "~4.6.0"
|
|
||||||
|
|
||||||
lodash.unset@^4.5.2:
|
lodash.unset@^4.5.2:
|
||||||
version "4.5.2"
|
version "4.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.unset/-/lodash.unset-4.5.2.tgz#370d1d3e85b72a7e1b0cdf2d272121306f23e4ed"
|
resolved "https://registry.yarnpkg.com/lodash.unset/-/lodash.unset-4.5.2.tgz#370d1d3e85b72a7e1b0cdf2d272121306f23e4ed"
|
||||||
|
@ -13048,14 +12980,6 @@ prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0,
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
react-is "^16.8.1"
|
react-is "^16.8.1"
|
||||||
|
|
||||||
proper-lockfile@^2.0.1:
|
|
||||||
version "2.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-2.0.1.tgz#159fb06193d32003f4b3691dd2ec1a634aa80d1d"
|
|
||||||
integrity sha1-FZ+wYZPTIAP0s2kd0uwaY0qoDR0=
|
|
||||||
dependencies:
|
|
||||||
graceful-fs "^4.1.2"
|
|
||||||
retry "^0.10.0"
|
|
||||||
|
|
||||||
property-information@^5.3.0:
|
property-information@^5.3.0:
|
||||||
version "5.6.0"
|
version "5.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69"
|
resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69"
|
||||||
|
@ -14321,11 +14245,6 @@ ret@~0.1.10:
|
||||||
version "0.1.15"
|
version "0.1.15"
|
||||||
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
||||||
|
|
||||||
retry@^0.10.0:
|
|
||||||
version "0.10.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
|
|
||||||
integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=
|
|
||||||
|
|
||||||
retry@^0.12.0:
|
retry@^0.12.0:
|
||||||
version "0.12.0"
|
version "0.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
|
resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
|
||||||
|
@ -15977,19 +15896,6 @@ tunnel@^0.0.6:
|
||||||
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
|
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
|
||||||
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
|
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
|
||||||
|
|
||||||
tus-js-client@^2.3.0:
|
|
||||||
version "2.3.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/tus-js-client/-/tus-js-client-2.3.0.tgz#5d76145476cea46a4e7c045a0054637cddf8dc39"
|
|
||||||
integrity sha512-I4cSwm6N5qxqCmBqenvutwSHe9ntf81lLrtf6BmLpG2v4wTl89atCQKqGgqvkodE6Lx+iKIjMbaXmfvStTg01g==
|
|
||||||
dependencies:
|
|
||||||
buffer-from "^0.1.1"
|
|
||||||
combine-errors "^3.0.3"
|
|
||||||
is-stream "^2.0.0"
|
|
||||||
js-base64 "^2.6.1"
|
|
||||||
lodash.throttle "^4.1.1"
|
|
||||||
proper-lockfile "^2.0.1"
|
|
||||||
url-parse "^1.4.3"
|
|
||||||
|
|
||||||
tween-functions@^1.2.0:
|
tween-functions@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/tween-functions/-/tween-functions-1.2.0.tgz#1ae3a50e7c60bb3def774eac707acbca73bbc3ff"
|
resolved "https://registry.yarnpkg.com/tween-functions/-/tween-functions-1.2.0.tgz#1ae3a50e7c60bb3def774eac707acbca73bbc3ff"
|
||||||
|
|
Loading…
Reference in a new issue