Merge pull request #1574 from lbryio/edit-no-source

Fix publish issues
This commit is contained in:
Sean Yesmunt 2018-06-12 23:44:41 -04:00 committed by GitHub
commit 277bc35095
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 182 additions and 116 deletions

View file

@ -48,7 +48,7 @@
"formik": "^0.10.4",
"hast-util-sanitize": "^1.1.2",
"keytar": "^4.2.1",
"lbry-redux": "lbryio/lbry-redux#7759bc6e8c482bed173d1f10aee6f6f9a439a15a",
"lbry-redux": "lbryio/lbry-redux#121ba56f47fff05531e27a7c99d7d417e79cd3ee",
"localforage": "^1.7.1",
"mixpanel-browser": "^2.17.1",
"moment": "^2.22.0",

View file

@ -1,32 +1,34 @@
// @flow
import * as React from 'react';
import Button from 'component/button';
import { buildURI } from 'lbry-redux';
import type { Claim } from 'types/claim';
type Props = {
uri: ?string,
editingURI: ?string,
isResolvingUri: boolean,
winningBidForClaimUri: ?number,
myClaimForUri: ?{},
onEditMyClaim: any => void,
myClaimForUri: ?Claim,
isStillEditing: boolean,
onEditMyClaim: (any, string) => void,
};
class BidHelpText extends React.PureComponent<Props> {
render() {
const {
uri,
editingURI,
isResolvingUri,
winningBidForClaimUri,
myClaimForUri,
onEditMyClaim,
isStillEditing,
} = this.props;
if (!uri) {
return __('Create a URL for this content');
}
if (uri === editingURI) {
if (isStillEditing) {
return __('You are currently editing this claim');
}
@ -35,11 +37,20 @@ class BidHelpText extends React.PureComponent<Props> {
}
if (myClaimForUri) {
const editUri = buildURI({
contentName: myClaimForUri.name,
claimId: myClaimForUri.claim_id,
});
return (
<React.Fragment>
{__('You already have a claim at')}
{` ${uri} `}
<Button button="link" label="Edit it" onClick={() => onEditMyClaim(myClaimForUri, uri)} />
<Button
button="link"
label="Edit it"
onClick={() => onEditMyClaim(myClaimForUri, editUri)}
/>
<br />
{__('Publishing will update your existing claim.')}
</React.Fragment>

View file

@ -49,6 +49,7 @@ type Props = {
bidError: ?string,
publishing: boolean,
balance: number,
isStillEditing: boolean,
clearPublish: () => void,
resolveUri: string => void,
scrollToTop: () => void,
@ -176,24 +177,13 @@ class PublishForm extends React.PureComponent<Props> {
handlePublish() {
const {
publish,
filePath,
bid,
title,
thumbnail,
description,
language,
nsfw,
copyrightNotice,
licenseType,
licenseUrl,
otherLicenseDescription,
copyrightNotice,
name,
contentIsFree,
price,
uri,
myClaimForUri,
channel,
publish,
} = this.props;
let publishingLicense;
@ -212,21 +202,22 @@ class PublishForm extends React.PureComponent<Props> {
const publishParams = {
filePath,
bid,
title,
thumbnail,
description,
language,
nsfw,
bid: this.props.bid,
title: this.props.title,
thumbnail: this.props.thumbnail,
description: this.props.description,
language: this.props.language,
nsfw: this.props.nsfw,
license: publishingLicense,
licenseUrl: publishingLicenseUrl,
otherLicenseDescription,
copyrightNotice,
name,
contentIsFree,
price,
uri,
channel,
name: this.props.name,
contentIsFree: this.props.contentIsFree,
price: this.props.price,
uri: this.props.uri,
channel: this.props.channel,
isStillEditing: this.props.isStillEditing,
};
// Editing a claim
@ -299,19 +290,12 @@ class PublishForm extends React.PureComponent<Props> {
clearPublish,
thumbnailPath,
resetThumbnailStatus,
isStillEditing,
} = this.props;
const formDisabled = (!filePath && !editingURI) || publishing;
const formValid = this.checkIsFormValid();
// The user could be linked from lbry://@channel... or lbry://claim-name...
// If a channel exists, we need to make sure it is added to the uri for proper edit handling
// If this isn't an edit, just use the pregenerated uri
const simpleUri = myClaimForUri
? buildURI({ channelName: myClaimForUri.channel_name, contentName: myClaimForUri.name })
: uri;
const isStillEditing = editingURI === simpleUri;
let submitLabel;
if (isStillEditing) {
submitLabel = !publishing ? __('Edit') : __('Editing...');
@ -463,7 +447,8 @@ class PublishForm extends React.PureComponent<Props> {
error={nameError}
helper={
<BidHelpText
uri={simpleUri}
isStillEditing={isStillEditing}
uri={uri}
editingURI={editingURI}
isResolvingUri={isResolvingUri}
winningBidForClaimUri={winningBidForClaimUri}

View file

@ -133,7 +133,12 @@ class FilePage extends React.Component<Props> {
// We will select the claim id before they publish
let editUri;
if (claimIsMine) {
editUri = buildURI({ channelName, contentName: claim.name });
const uriObject = { contentName: claim.name, claimId: claim.claim_id };
if (channelName) {
uriObject.channelName = channelName;
}
editUri = buildURI(uriObject);
}
return (

View file

@ -1,12 +1,11 @@
import { connect } from 'react-redux';
import { selectMyClaimsWithoutChannels } from 'lbry-redux';
import { selectPendingPublishes } from 'redux/selectors/publish';
import { selectPendingPublishes, selectClaimsWithPendingPublishes } from 'redux/selectors/publish';
import { doNavigate } from 'redux/actions/navigation';
import { doCheckPendingPublishes } from 'redux/actions/publish';
import FileListPublished from './view';
const select = state => ({
claims: selectMyClaimsWithoutChannels(state),
claims: selectClaimsWithPendingPublishes(state),
pendingPublishes: selectPendingPublishes(state),
});
@ -15,4 +14,7 @@ const perform = dispatch => ({
checkIfPublishesConfirmed: publishes => dispatch(doCheckPendingPublishes(publishes)),
});
export default connect(select, perform)(FileListPublished);
export default connect(
select,
perform
)(FileListPublished);

View file

@ -20,13 +20,12 @@ class FileListPublished extends React.PureComponent<Props> {
}
render() {
const { claims, pendingPublishes, navigate } = this.props;
const fileInfos = [...pendingPublishes, ...claims];
const { claims, navigate } = this.props;
return (
<Page notContained>
{fileInfos.length ? (
<FileList checkPending fileInfos={fileInfos} sortByHeight />
{claims.length ? (
<FileList checkPending fileInfos={claims} sortByHeight />
) : (
<div className="page__empty">
{__("It looks like you haven't published anything to LBRY yet.")}

View file

@ -1,14 +1,11 @@
import { connect } from 'react-redux';
import {
doResolveUri,
makeSelectCostInfoForUri,
selectMyClaims,
selectClaimsByUri,
selectResolvingUris,
selectBalance,
} from 'lbry-redux';
import { doResolveUri, selectClaimsByUri, selectResolvingUris, selectBalance } from 'lbry-redux';
import { doNavigate } from 'redux/actions/navigation';
import { selectPublishFormValues } from 'redux/selectors/publish';
import {
selectPublishFormValues,
selectIsStillEditing,
selectMyClaimForUri,
} from 'redux/selectors/publish';
import {
doResetThumbnailStatus,
doClearPublish,
@ -18,9 +15,11 @@ import {
} from 'redux/actions/publish';
import PublishPage from './view';
const select = (state, props) => {
const select = state => {
const isStillEditing = selectIsStillEditing(state);
const myClaimForUri = selectMyClaimForUri(state);
const publishState = selectPublishFormValues(state);
const { uri, name } = publishState;
const { uri } = publishState;
const resolvingUris = selectResolvingUris(state);
let isResolvingUri = false;
@ -28,24 +27,28 @@ const select = (state, props) => {
isResolvingUri = resolvingUris.includes(uri);
}
const claimsByUri = selectClaimsByUri(state);
const myClaims = selectMyClaims(state);
const claimForUri = claimsByUri[uri];
let claimForUri;
let winningBidForClaimUri;
let myClaimForUri;
if (claimForUri) {
winningBidForClaimUri = claimForUri.effective_amount;
myClaimForUri = myClaims.find(claim => claim.name === name);
if (!myClaimForUri) {
// if the uri isn't from a users claim, find the winning bid needed for the vanity url
// in the future we may want to display this on users claims
// ex: "you own this, for 5 more lbc you will win this claim"
const claimsByUri = selectClaimsByUri(state);
claimForUri = claimsByUri[uri];
winningBidForClaimUri = claimForUri ? claimForUri.effective_amount : null;
}
return {
...publishState,
isResolvingUri,
// The winning claim for a short lbry uri
claimForUri,
winningBidForClaimUri,
// My previously published claims under this short lbry uri
myClaimForUri,
costInfo: makeSelectCostInfoForUri(props.uri)(state),
// If I clicked the "edit" button, have I changed the uri?
// Need this to make it easier to find the source on previously published content
isStillEditing,
balance: selectBalance(state),
};
};
@ -56,8 +59,11 @@ const perform = dispatch => ({
resolveUri: uri => dispatch(doResolveUri(uri)),
publish: params => dispatch(doPublish(params)),
navigate: path => dispatch(doNavigate(path)),
prepareEdit: claim => dispatch(doPrepareEdit(claim)),
prepareEdit: (claim, uri) => dispatch(doPrepareEdit(claim, uri)),
resetThumbnailStatus: () => dispatch(doResetThumbnailStatus()),
});
export default connect(select, perform)(PublishPage);
export default connect(
select,
perform
)(PublishPage);

View file

@ -2,7 +2,6 @@
import {
ACTIONS,
Lbry,
selectMyClaimsWithoutChannels,
doNotify,
MODALS,
selectMyChannelClaims,
@ -168,7 +167,6 @@ export const doPrepareEdit = (claim: any, uri: string) => (dispatch: Dispatch) =
export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getState: () => {}) => {
const state = getState();
const myClaims = selectMyClaimsWithoutChannels(state);
const myChannels = selectMyChannelClaims(state);
const {
@ -187,23 +185,12 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat
price,
uri,
sources,
isStillEditing,
} = params;
// get the claim id from the channel name, we will use that instead
const namedChannelClaim = myChannels.find(myChannel => myChannel.name === channel);
const channelId = namedChannelClaim ? namedChannelClaim.claim_id : '';
let isEdit;
const newPublishName = channel ? `${channel}/${name}` : name;
for (let i = 0; i < myClaims.length; i += 1) {
const { channel_name: claimChannelName, name: claimName } = myClaims[i];
const contentName = claimChannelName ? `${claimChannelName}/${claimName}` : claimName;
if (contentName === newPublishName) {
isEdit = true;
break;
}
}
const fee = contentIsFree || !price.amount ? undefined : { ...price };
const metadata = {
@ -241,7 +228,7 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat
const success = () => {
dispatch({
type: ACTIONS.PUBLISH_SUCCESS,
data: { pendingPublish: { ...publishPayload, isEdit } },
data: { pendingPublish: { ...publishPayload, isEdit: isStillEditing } },
});
dispatch(doNotify({ id: MODALS.PUBLISH }, { uri }));
};
@ -258,38 +245,40 @@ export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getStat
export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetState) => {
const state = getState();
const pendingPublishes = selectPendingPublishes(state);
const myClaims = selectMyClaimsWithoutChannels(state);
let publishCheckInterval;
const checkFileList = () => {
Lbry.claim_list_mine().then(claims => {
const claimsWithoutChannels = claims.filter(claim => !claim.name.match(/^@/));
if (myClaims.length !== claimsWithoutChannels.length) {
const pendingPublishMap = {};
pendingPublishes.forEach(({ name }) => {
pendingPublishMap[name] = name;
});
const pendingPublishMap = {};
pendingPublishes.forEach(({ name }) => {
pendingPublishMap[name] = name;
});
claims.forEach(claim => {
if (pendingPublishMap[claim.name]) {
dispatch({
type: ACTIONS.REMOVE_PENDING_PUBLISH,
data: {
name: claim.name,
},
});
dispatch({
type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED,
data: {
claims,
},
});
const actions = [];
claims.forEach(claim => {
if (pendingPublishMap[claim.name]) {
actions.push({
type: ACTIONS.REMOVE_PENDING_PUBLISH,
data: {
name: claim.name,
},
});
delete pendingPublishMap[claim.name];
}
});
delete pendingPublishMap[claim.name];
}
});
actions.push({
type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED,
data: {
claims,
},
});
dispatch(batchActions(...actions));
if (!pendingPublishes.length) {
clearInterval(publishCheckInterval);
}
});

View file

@ -169,18 +169,23 @@ export default handleActions(
};
},
[ACTIONS.DO_PREPARE_EDIT]: (state: PublishState, action) => {
const { pendingPublishes } = state;
const { ...publishData } = action.data;
const { channel, name } = publishData;
const { channel, name, uri } = publishData;
const uri = buildURI({
// The short uri is what is presented to the user
// The editingUri is the full uri with claim id
const shortUri = buildURI({
channelName: channel,
contentName: name,
});
return {
...defaultState,
editingURI: uri,
...publishData,
pendingPublishes,
editingURI: uri,
uri: shortUri,
};
},
},

View file

@ -1,5 +1,5 @@
import { createSelector } from 'reselect';
import { parseURI } from 'lbry-redux';
import { parseURI, selectClaimsById, selectMyClaimsWithoutChannels } from 'lbry-redux';
const selectState = state => state.publish || {};
@ -8,6 +8,24 @@ export const selectPendingPublishes = createSelector(
state => state.pendingPublishes.map(pendingClaim => ({ ...pendingClaim, pending: true })) || []
);
export const selectClaimsWithPendingPublishes = createSelector(
selectMyClaimsWithoutChannels,
selectPendingPublishes,
(claims, pendingPublishes) => {
// ensure there are no duplicates, they are being checked for in a setInterval
// no need to wait for it to complete though
// loop through myclaims
// if a claim has the same name as one in pendingPublish, remove it from pending
const claimMap = {};
claims.forEach(claim => {
claimMap[claim.name] = true;
});
const filteredPendingPublishes = pendingPublishes.filter(claim => !claimMap[claim.name]);
return [...claims, ...filteredPendingPublishes];
}
);
export const selectPublishFormValues = createSelector(selectState, state => {
const { pendingPublish, ...formValues } = state;
return formValues;
@ -25,3 +43,49 @@ export const selectPendingPublish = uri =>
publish => (publish.name === claimName || publish.name === contentName) && !publish.isEdit
)[0];
});
// Is the current uri the same as the uri they clicked "edit" on
export const selectIsStillEditing = createSelector(selectPublishFormValues, publishState => {
const { editingURI, uri } = publishState;
const {
isChannel: currentIsChannel,
claimName: currentClaimName,
contentName: currentContentName,
} = parseURI(uri);
const {
isChannel: editIsChannel,
claimName: editClaimName,
contentName: editContentName,
} = parseURI(editingURI);
// Depending on the previous/current use of a channel, we need to compare different things
// ex: going from a channel to anonymous, the new uri won't return contentName, so we need to use claimName
const currentName = currentIsChannel ? currentContentName : currentClaimName;
const editName = editIsChannel ? editContentName : editClaimName;
return currentName === editName;
});
export const selectMyClaimForUri = createSelector(
selectPublishFormValues,
selectIsStillEditing,
selectClaimsById,
selectMyClaimsWithoutChannels,
({ editingURI, uri }, isStillEditing, claimsById, myClaims) => {
const { contentName, claimName } = parseURI(uri);
const { claimId: editClaimId } = parseURI(editingURI);
// If isStillEditing
// They clicked "edit" from the file page
// They haven't changed the channel/name after clicking edit
// Get the claim so they can edit without re-uploading a new file
return isStillEditing
? claimsById[editClaimId]
: myClaims.find(
claim =>
!contentName
? claim.name === claimName
: claim.name === contentName || claim.name === claimName
);
}
);

View file

@ -5564,9 +5564,9 @@ lazy-val@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc"
lbry-redux@lbryio/lbry-redux#7759bc6e8c482bed173d1f10aee6f6f9a439a15a:
lbry-redux@lbryio/lbry-redux#121ba56f47fff05531e27a7c99d7d417e79cd3ee:
version "0.0.1"
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/7759bc6e8c482bed173d1f10aee6f6f9a439a15a"
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/121ba56f47fff05531e27a7c99d7d417e79cd3ee"
dependencies:
proxy-polyfill "0.1.6"
reselect "^3.0.0"