From da06c14e6088d9d39fa26bf7a6fee1b63044655f Mon Sep 17 00:00:00 2001 From: Dan Peterson Date: Fri, 31 Dec 2021 11:20:54 -0600 Subject: [PATCH] Fix publish form when editing livestream (#565) * Update publish form when editing livestream + update to radios for liveststream release time * Fix bug where upload tools may remain visible upon switching upload type, even when no option to upload is available. * move publish source state up, when editing livestream only show scheduling option when source is none. * Reset any set release time if switching to live stream mode. * Update date/time cmpnts to reset any chnages they made on umount. Update schedule date/time cmpnt to clear release time when selecting anytime option. * Additional filtering of internal tags * Default to replay view when editing a liveststream --- .../publishAdditionalOptions/view.jsx | 6 +- ui/component/publishFile/view.jsx | 207 ++++++++++-------- ui/component/publishForm/view.jsx | 28 ++- ui/component/publishReleaseDate/view.jsx | 8 +- .../publishStreamReleaseDate/view.jsx | 8 +- ui/constants/publish_sources.js | 3 + ui/modal/modalPublishPreview/view.jsx | 5 +- ui/redux/selectors/claims.js | 3 + 8 files changed, 155 insertions(+), 113 deletions(-) create mode 100644 ui/constants/publish_sources.js diff --git a/ui/component/publishAdditionalOptions/view.jsx b/ui/component/publishAdditionalOptions/view.jsx index 4fe3eb636..64cfc6fd3 100644 --- a/ui/component/publishAdditionalOptions/view.jsx +++ b/ui/component/publishAdditionalOptions/view.jsx @@ -29,7 +29,7 @@ type Props = { needsYTAuth: boolean, fetchAccessToken: () => void, accessToken: string, - isLivestreamMode: boolean, + showSchedulingOptions: boolean, }; function PublishAdditionalOptions(props: Props) { @@ -40,7 +40,7 @@ function PublishAdditionalOptions(props: Props) { otherLicenseDescription, licenseUrl, updatePublishForm, - isLivestreamMode, + showSchedulingOptions, // user, // useLBRYUploader, // needsYTAuth, @@ -156,7 +156,7 @@ function PublishAdditionalOptions(props: Props) { )} */} {/* @endif */}
- {!isLivestreamMode && } + {!showSchedulingOptions && } void, + fileSelectSource: string, + changeFileSelectSource: (string) => void, }; function PublishFile(props: Props) { @@ -84,12 +87,10 @@ function PublishFile(props: Props) { channelSignature, isCheckingLivestreams, setWaitForFile, + fileSelectSource, + changeFileSelectSource, } = props; - const SOURCE_NONE = 'none'; - const SOURCE_SELECT = 'select'; - const SOURCE_UPLOAD = 'upload'; - const RECOMMENDED_BITRATE = 6000000; const TV_PUBLISH_SIZE_LIMIT_BYTES = WEB_PUBLISH_SIZE_LIMIT_GB * 1073741824; const TV_PUBLISH_SIZE_LIMIT_GB_STR = String(WEB_PUBLISH_SIZE_LIMIT_GB); @@ -114,16 +115,13 @@ function PublishFile(props: Props) { const fileSelectorModes = [ { label: __('Upload'), actionName: SOURCE_UPLOAD, icon: ICONS.PUBLISH }, { label: __('Choose Replay'), actionName: SOURCE_SELECT, icon: ICONS.MENU }, - { label: __('None'), actionName: SOURCE_NONE }, + { label: isLivestreamClaim ? __('Edit / Update') : __('None'), actionName: SOURCE_NONE }, ]; const livestreamDataStr = JSON.stringify(livestreamData); const hasLivestreamData = livestreamData && Boolean(livestreamData.length); const showSourceSelector = isLivestreamClaim || (hasLivestreamData && mode === PUBLISH_MODES.FILE); - const [fileSelectSource, setFileSelectSource] = useState( - IS_WEB && showSourceSelector && name ? SOURCE_SELECT : SOURCE_UPLOAD - ); // const [showFileUpdate, setShowFileUpdate] = useState(false); const [selectedFileIndex, setSelectedFileIndex] = useState(null); const PAGE_SIZE = 4; @@ -142,15 +140,21 @@ function PublishFile(props: Props) { } }, [currentFileType, mode, isStillEditing, updatePublishForm]); - // set default file source to select if necessary + // Initialize default file source state. useEffect(() => { - if (hasLivestreamData && isLivestreamClaim) { - setWaitForFile(true); - setFileSelectSource(SOURCE_SELECT); - } else if (isLivestreamClaim) { - setFileSelectSource(SOURCE_NONE); + // Editing a livestream + if (isLivestreamClaim) { + changeFileSelectSource(SOURCE_SELECT); } - }, [hasLivestreamData, isLivestreamClaim, setFileSelectSource]); + // Publishing a livestream + else if (mode === PUBLISH_MODES.LIVESTREAM) { + changeFileSelectSource(SOURCE_NONE); + } else if (showSourceSelector && name) { + changeFileSelectSource(SOURCE_SELECT); + } else { + changeFileSelectSource(SOURCE_UPLOAD); + } + }, [mode]); // eslint-disable-line react-hooks/exhaustive-deps const normalizeUrlForProtocol = (url) => { if (url.startsWith('https://')) { @@ -328,7 +332,7 @@ function PublishFile(props: Props) { updatePublishForm({ remoteFileUrl: livestreamData[selectedFileIndex].data.fileLocation }); } } - setFileSelectSource(source); + changeFileSelectSource(source); setWaitForFile(source !== SOURCE_NONE); } @@ -437,7 +441,7 @@ function PublishFile(props: Props) { updatePublishForm(publishFormParams); } - const showFileUpload = mode === PUBLISH_MODES.FILE; + const showFileUpload = mode === PUBLISH_MODES.FILE || PUBLISH_MODES.LIVESTREAM; const isPublishPost = mode === PUBLISH_MODES.POST; return ( @@ -514,7 +518,7 @@ function PublishFile(props: Props) { )} - {fileSelectSource === SOURCE_UPLOAD && showFileUpload && ( + {showSourceSelector && fileSelectSource === SOURCE_UPLOAD && showFileUpload && ( <> )} - {fileSelectSource === SOURCE_SELECT && showFileUpload && hasLivestreamData && !isCheckingLivestreams && ( - <> - - -
- - - {livestreamData.slice((currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE).map((item, i) => ( - setSelectedFileIndex((currentPage - 1) * PAGE_SIZE + i)} - key={item.id} - className={classnames('livestream__data-row', { - 'livestream__data-row--selected': selectedFileIndex === (currentPage - 1) * PAGE_SIZE + i, - })} - > - - - - - - ))} - -
- setSelectedFileIndex((currentPage - 1) * PAGE_SIZE + i)} - className="livestream__data-row-radio" - /> - -
- {item.data.thumbnails.slice(0, 3).map((thumb) => ( - - ))} -
-
- {`${Math.floor(item.data.fileDuration / 60)} ${ - Math.floor(item.data.fileDuration / 60) > 1 ? __('minutes') : __('minute') - }`} -
- {`${moment(item.data.uploadedAt).from(moment())}`} -
-
- -
-
-
- + {showSourceSelector && + fileSelectSource === SOURCE_SELECT && + showFileUpload && + hasLivestreamData && + !isCheckingLivestreams && ( + <> - handlePaginateReplays(e.selected + 1)} - forcePage={currentPage - 1} - initialPage={currentPage - 1} - containerClassName="pagination" - /> + +
+ + + {livestreamData + .slice((currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE) + .map((item, i) => ( + setSelectedFileIndex((currentPage - 1) * PAGE_SIZE + i)} + key={item.id} + className={classnames('livestream__data-row', { + 'livestream__data-row--selected': + selectedFileIndex === (currentPage - 1) * PAGE_SIZE + i, + })} + > + + + + + + ))} + +
+ setSelectedFileIndex((currentPage - 1) * PAGE_SIZE + i)} + className="livestream__data-row-radio" + /> + +
+ {item.data.thumbnails.slice(0, 3).map((thumb) => ( + + ))} +
+
+ {`${Math.floor(item.data.fileDuration / 60)} ${ + Math.floor(item.data.fileDuration / 60) > 1 ? __('minutes') : __('minute') + }`} +
+ {`${moment(item.data.uploadedAt).from(moment())}`} +
+
+ +
+
-
- - )} - {fileSelectSource === SOURCE_SELECT && showFileUpload && !hasLivestreamData && !isCheckingLivestreams && ( -
- -
- )} - {fileSelectSource === SOURCE_SELECT && showFileUpload && isCheckingLivestreams && ( + + + handlePaginateReplays(e.selected + 1)} + forcePage={currentPage - 1} + initialPage={currentPage - 1} + containerClassName="pagination" + /> + + + + )} + {showSourceSelector && + fileSelectSource === SOURCE_SELECT && + showFileUpload && + !hasLivestreamData && + !isCheckingLivestreams && ( +
+ +
+ )} + {showSourceSelector && fileSelectSource === SOURCE_SELECT && showFileUpload && isCheckingLivestreams && (
diff --git a/ui/component/publishForm/view.jsx b/ui/component/publishForm/view.jsx index aa11ca2d3..d4df2889d 100644 --- a/ui/component/publishForm/view.jsx +++ b/ui/component/publishForm/view.jsx @@ -32,6 +32,7 @@ import Spinner from 'component/spinner'; import { toHex } from 'util/hex'; import { LIVESTREAM_REPLAY_API } from 'constants/livestream'; import PublishStreamReleaseDate from 'component/publishStreamReleaseDate'; +import { SOURCE_NONE } from 'constants/publish_sources'; // @if TARGET='app' import fs from 'fs'; @@ -173,7 +174,8 @@ function PublishForm(props: Props) { [PUBLISH_MODES.LIVESTREAM]: 'Livestream --[noun, livestream tab button]--', }; - const [mode, setMode] = React.useState(_uploadType || PUBLISH_MODES.FILE); + const defaultPublishMode = isLivestreamClaim ? PUBLISH_MODES.LIVESTREAM : PUBLISH_MODES.FILE; + const [mode, setMode] = React.useState(_uploadType || defaultPublishMode); const [isCheckingLivestreams, setCheckingLivestreams] = React.useState(false); let customSubtitle; @@ -422,9 +424,8 @@ function PublishForm(props: Props) { // set mode based on urlParams 'type' useEffect(() => { - // Default to standard file publish if none specified if (!_uploadType) { - setMode(PUBLISH_MODES.FILE); + setMode(defaultPublishMode); return; } @@ -448,9 +449,8 @@ function PublishForm(props: Props) { return; } - // Default to standard file publish - setMode(PUBLISH_MODES.FILE); - }, [_uploadType, enableLivestream]); + setMode(defaultPublishMode); + }, [_uploadType, enableLivestream, defaultPublishMode]); // if we have a type urlparam, update it? necessary? useEffect(() => { @@ -560,6 +560,15 @@ function PublishForm(props: Props) { } }, [mode, updatePublishForm]); + // Source Selector State. + const [fileSelectSource, setFileSelectSource] = useState(); + const changeFileSelectSource = (state) => setFileSelectSource(state); + + const [showSchedulingOptions, setShowSchedulingOptions] = useState(false); + useEffect(() => { + setShowSchedulingOptions(isLivestreamMode && fileSelectSource === SOURCE_NONE); + }, [isLivestreamMode, fileSelectSource]); + if (publishing) { return (
@@ -568,12 +577,15 @@ function PublishForm(props: Props) {
); } + // Editing claim uri return (
- {isLivestreamMode && } />} + {showSchedulingOptions && } />} {mode !== PUBLISH_MODES.POST && } @@ -646,7 +658,7 @@ function PublishForm(props: Props) { {!isLivestreamMode && } - +
)}
diff --git a/ui/component/publishReleaseDate/view.jsx b/ui/component/publishReleaseDate/view.jsx index bb6ab0ff5..c45039c17 100644 --- a/ui/component/publishReleaseDate/view.jsx +++ b/ui/component/publishReleaseDate/view.jsx @@ -1,5 +1,5 @@ // @flow -import React from 'react'; +import React, { useEffect } from 'react'; import Button from 'component/button'; import DateTimePicker from 'react-datetime-picker'; @@ -86,6 +86,12 @@ const PublishReleaseDate = (props: Props) => { } } + useEffect(() => { + return () => { + updatePublishForm({ releaseTimeEdited: undefined }); + }; + }, []); + return (
diff --git a/ui/component/publishStreamReleaseDate/view.jsx b/ui/component/publishStreamReleaseDate/view.jsx index 837ffce20..7a7428477 100644 --- a/ui/component/publishStreamReleaseDate/view.jsx +++ b/ui/component/publishStreamReleaseDate/view.jsx @@ -59,8 +59,8 @@ const PublishStreamReleaseDate = (props: Props) => {
{
{

{licenseType}

); + const visibleTags = tags.filter((tag) => !INTERNAL_TAGS.includes(tag.name)); + const tagsValue = // Do nothing for onClick(). Setting to 'null' results in "View Tag" action -- we don't want to leave the modal. - tags.map((tag) => {}} />); + visibleTags.map((tag) => {}} />); const depositValue = bid ? :

---

; diff --git a/ui/redux/selectors/claims.js b/ui/redux/selectors/claims.js index cec63c76b..9e6db9fe2 100644 --- a/ui/redux/selectors/claims.js +++ b/ui/redux/selectors/claims.js @@ -333,6 +333,9 @@ export const makeSelectMetadataForUri = (uri: string) => export const makeSelectMetadataItemForUri = (uri: string, key: string) => createSelector(makeSelectMetadataForUri(uri), (metadata: ChannelMetadata | StreamMetadata) => { + if (key === 'tags') { + return metadata.tags ? metadata.tags.filter((tag) => !INTERNAL_TAGS.includes(tag)) : []; + } return metadata ? metadata[key] : undefined; });