channel and file selector fixes

This commit is contained in:
Jeremy Kauffman 2017-05-21 10:42:34 -04:00
parent bb16156034
commit 951190bf96
15 changed files with 127 additions and 79 deletions

View file

@ -26,6 +26,8 @@ import {
export function doResolveUri(uri) { export function doResolveUri(uri) {
return function(dispatch, getState) { return function(dispatch, getState) {
uri = lbryuri.normalize(uri)
const state = getState() const state = getState()
const alreadyResolving = selectResolvingUris(state).indexOf(uri) !== -1 const alreadyResolving = selectResolvingUris(state).indexOf(uri) !== -1
@ -81,14 +83,6 @@ export function doFetchFeaturedUris() {
featuredUris[category] = Uris[category] featuredUris[category] = Uris[category]
} }
}) })
//
// dispatch({
// type: types.FETCH_FEATURED_CONTENT_COMPLETED,
// data: {
// categories: ["FOO"],
// uris: { FOO: ["lbry://gtasoc"]},
// }
// })
dispatch({ dispatch({
type: types.FETCH_FEATURED_CONTENT_COMPLETED, type: types.FETCH_FEATURED_CONTENT_COMPLETED,

View file

@ -1,4 +1,4 @@
import * as types from 'constants/action_types' import * as types from 'constants/action_types'
import lbry from 'lbry' import lbry from 'lbry'
import lbryio from 'lbryio' import lbryio from 'lbryio'
import { import {

View file

@ -118,7 +118,7 @@ class FileActions extends React.Component {
<DropDownMenuItem key={1} onClick={() => openModal('confirmRemove')} label="Remove..." /> <DropDownMenuItem key={1} onClick={() => openModal('confirmRemove')} label="Remove..." />
</DropDownMenu> : '' } </DropDownMenu> : '' }
<Modal type="confirm" isOpen={modal == 'affirmPurchase'} <Modal type="confirm" isOpen={modal == 'affirmPurchase'}
contentLabel="Confirm Purchase" onConfirmed={this.onAffirmPurchase.bind(this)} onAborted={this.closeModal.bind(this)}> contentLabel="Confirm Purchase" onConfirmed={this.onAffirmPurchase.bind(this)} onAborted={this.props.closeModal}>
This will purchase <strong>{title}</strong> for <strong><FilePrice uri={uri} look="plain" /></strong> credits. This will purchase <strong>{title}</strong> for <strong><FilePrice uri={uri} look="plain" /></strong> credits.
</Modal> </Modal>
<Modal isOpen={modal == 'notEnoughCredits'} contentLabel="Not enough credits" <Modal isOpen={modal == 'notEnoughCredits'} contentLabel="Not enough credits"

View file

@ -32,7 +32,7 @@ export class FormField extends React.Component {
} }
componentWillMount() { componentWillMount() {
if (['text', 'number', 'radio', 'checkbox', 'file'].includes(this.props.type)) { if (['text', 'number', 'radio', 'checkbox'].includes(this.props.type)) {
this._element = 'input'; this._element = 'input';
this._type = this.props.type; this._type = this.props.type;
} else if (this.props.type == 'text-number') { } else if (this.props.type == 'text-number') {
@ -118,7 +118,7 @@ export class FormField extends React.Component {
</label> : </label> :
element } element }
{ formFieldFileSelectorTypes.includes(this.props.type) ? { formFieldFileSelectorTypes.includes(this.props.type) ?
<FileSelector type={this.props.type} onFileChosen={this.handleFileChosen} <FileSelector type={this.props.type} onFileChosen={this.handleFileChosen.bind(this)}
{... this.props.defaultValue ? {initPath: this.props.defaultValue} : {}} /> : {... this.props.defaultValue ? {initPath: this.props.defaultValue} : {}} /> :
null } null }
{ this.props.postfix ? <span className="form-field__postfix">{this.props.postfix}</span> : '' } { this.props.postfix ? <span className="form-field__postfix">{this.props.postfix}</span> : '' }

View file

@ -30,11 +30,11 @@ export class RewardLink extends React.Component {
return; return;
case 'first_publish': case 'first_publish':
lbry.claim_list_mine().then(function(list) { lbry.claim_list_mine().then((list) => {
this.setState({ this.setState({
claimable: list.length > 0 claimable: list.length > 0
}) })
}.bind(this)); });
return; return;
} }
} }

View file

@ -1,20 +1,31 @@
import React from 'react' import React from 'react'
import lbryuri from 'lbryuri';
import { import {
connect, connect,
} from 'react-redux' } from 'react-redux'
import {
makeSelectIsResolvingForUri
} from 'selectors/content'
import { import {
makeSelectClaimForUri, makeSelectClaimForUri,
} from 'selectors/claims' } from 'selectors/claims'
import UriIndicator from './view' import UriIndicator from './view'
const makeSelect = () => { const makeSelect = () => {
const selectClaimForUri = makeSelectClaimForUri() const selectClaim = makeSelectClaimForUri(),
selectIsResolving = makeSelectIsResolvingForUri();
const select = (state, props) => ({ const select = (state, props) => ({
claim: selectClaimForUri(state, props), claim: selectClaim(state, props),
isResolvingUri: selectIsResolving(state, props),
uri: lbryuri.normalize(props.uri),
}) })
return select return select
} }
export default connect(makeSelect, null)(UriIndicator) const perform = (dispatch) => ({
resolveUri: (uri) => dispatch(doResolveUri(uri))
})
export default connect(makeSelect, perform)(UriIndicator)

View file

@ -1,50 +1,74 @@
import React from 'react'; import React from 'react';
import lbry from 'lbry';
import lbryuri from 'lbryuri';
import {Icon} from 'component/common'; import {Icon} from 'component/common';
const UriIndicator = (props) => { class UriIndicator extends React.Component{
const { componentWillMount() {
uri, this.resolve(this.props)
claim
} = props
const uriObj = lbryuri.parse(uri);
if (!claim) {
return <span className="empty">Unused</span>
} }
const { componentWillReceiveProps(nextProps) {
has_signature: hasSignature, this.resolve(nextProps)
signature_is_valid: signatureIsValid
} = claim
if (!hasSignature || !uriObj.isChannel) {
return <span className="empty">Anonymous</span>;
} }
const channelUriObj = Object.assign({}, uriObj); resolve(props) {
delete channelUriObj.path; const {
delete channelUriObj.contentName; isResolvingUri,
const channelUri = lbryuri.build(channelUriObj, false); resolveUri,
claim,
uri,
} = props
let icon, modifier; if(!isResolvingUri && claim === undefined && uri) {
if (signatureIsValid) { resolveUri(uri)
modifier = 'valid'; }
} else {
icon = 'icon-times-circle';
modifier = 'invalid';
} }
return ( render() {
<span> const {
{channelUri} {' '} claim,
{ !signatureIsValid ? uri,
<Icon icon={icon} className={`channel-indicator__icon channel-indicator__icon--${modifier}`} /> : isResolvingUri
'' } } = this.props
</span>
) if (isResolvingUri) {
return <span className="empty">Validating...</span>
}
if (!claim) {
return <span className="empty">Unused</span>
}
const {
channel_name: channelName,
has_signature: hasSignature,
signature_is_valid: signatureIsValid,
} = claim
console.log('uri indicator render')
console.log(uri)
console.log(claim)
if (!hasSignature || !channelName) {
return <span className="empty">Anonymous</span>;
}
let icon, modifier;
if (signatureIsValid) {
modifier = 'valid';
} else {
icon = 'icon-times-circle';
modifier = 'invalid';
}
return (
<span>
{channelName} {' '}
{ !signatureIsValid ?
<Icon icon={icon} className={`channel-indicator__icon channel-indicator__icon--${modifier}`} /> :
'' }
</span>
)
}
} }
export default UriIndicator; export default UriIndicator;

View file

@ -11,8 +11,6 @@ import {
} from 'selectors/claims' } from 'selectors/claims'
import ChannelPage from './view' import ChannelPage from './view'
import FilePage from './view'
const makeSelect = () => { const makeSelect = () => {
const selectClaim = makeSelectClaimForUri(), const selectClaim = makeSelectClaimForUri(),
selectClaimsInChannel = makeSelectClaimsInChannelForUri() selectClaimsInChannel = makeSelectClaimsInChannelForUri()
@ -26,7 +24,6 @@ const makeSelect = () => {
} }
const perform = (dispatch) => ({ const perform = (dispatch) => ({
// fetchClaims: () => { console.log('fetch claims') }
fetchClaims: (uri) => dispatch(doFetchClaimsByChannel(uri)) fetchClaims: (uri) => dispatch(doFetchClaimsByChannel(uri))
}) })

View file

@ -1,5 +1,7 @@
import React from 'react'; import React from 'react';
import lbryuri from 'lbryuri' import lbryuri from 'lbryuri'
import {BusyMessage} from 'component/common'
import FileTile from 'component/fileTile'
class ChannelPage extends React.Component{ class ChannelPage extends React.Component{
componentDidMount() { componentDidMount() {
@ -23,7 +25,15 @@ class ChannelPage extends React.Component{
uri uri
} = this.props } = this.props
console.log(claimsInChannel); let contentList
if (claimsInChannel === undefined) {
contentList = <BusyMessage message="Fetching content" />
} else if (claimsInChannel) {
contentList = claimsInChannel.length ?
claimsInChannel.map((claim) => <FileTile key={claim.claim_id} uri={lbryuri.build({name: claim.name, claimId: claim.claim_id})} />) :
<span className="empty">No content found.</span>
}
return <main className="main--single-column"> return <main className="main--single-column">
<section className="card"> <section className="card">
<div className="card__inner"> <div className="card__inner">
@ -35,13 +45,8 @@ class ChannelPage extends React.Component{
</p> </p>
</div> </div>
</section> </section>
<section className="card"> <h3 className="card-row__header">Published Content</h3>
<div className="card__content"> {contentList}
{claimsInChannel ?
claimsInChannel.map((claim) => <FileTile uri={lbryuri.build({name: claim.name, claimId: claim.claim_id})} /> )
: ''}
</div>
</section>
</main> </main>
} }
} }

View file

@ -2,6 +2,9 @@ import React from 'react'
import { import {
connect connect
} from 'react-redux' } from 'react-redux'
import {
doNavigate,
} from 'actions/app'
import { import {
doFetchFileInfo, doFetchFileInfo,
} from 'actions/file_info' } from 'actions/file_info'
@ -37,6 +40,7 @@ const makeSelect = () => {
} }
const perform = (dispatch) => ({ const perform = (dispatch) => ({
navigate: (path, params) => dispatch(doNavigate(path, params)),
fetchFileInfo: (uri) => dispatch(doFetchFileInfo(uri)) fetchFileInfo: (uri) => dispatch(doFetchFileInfo(uri))
}) })

View file

@ -74,6 +74,7 @@ class FilePage extends React.Component{
const { const {
txid, txid,
nout, nout,
channel_name: channelName,
has_signature: hasSignature, has_signature: hasSignature,
signature_is_valid: signatureIsValid, signature_is_valid: signatureIsValid,
value value
@ -81,10 +82,8 @@ class FilePage extends React.Component{
const outpoint = txid + ':' + nout const outpoint = txid + ':' + nout
const title = metadata.title const title = metadata.title
const channelUriObj = lbryuri.parse(uri) const channelClaimId = claim.value && claim.value.publisherSignature ? claim.value.publisherSignature.certificateId : null;
delete channelUriObj.path; const channelUri = signatureIsValid && hasSignature && channelName ? lbryuri.build({channelName, claimId: channelClaimId}, false) : null
delete channelUriObj.contentName;
const channelUri = signatureIsValid && hasSignature && channelUriObj.isChannel ? lbryuri.build(channelUriObj, false) : null
const uriIndicator = <UriIndicator uri={uri} /> const uriIndicator = <UriIndicator uri={uri} />
return ( return (
@ -102,7 +101,7 @@ class FilePage extends React.Component{
: null}<h1>{title}</h1> : null}<h1>{title}</h1>
<div className="card__subtitle"> <div className="card__subtitle">
{ channelUri ? { channelUri ?
<Link href={"?show=" + channelUri }>{uriIndicator}</Link> : <Link onClick={() => this.props.navigate('/show', { uri: channelUri })}>{uriIndicator}</Link> :
uriIndicator} uriIndicator}
</div> </div>
<div className="card__actions"> <div className="card__actions">

View file

@ -8,8 +8,6 @@ import {BusyMessage} from 'component/common.js';
class SearchPage extends React.Component{ class SearchPage extends React.Component{
render() { render() {
console.log('render search page')
const { const {
query, query,
} = this.props } = this.props

View file

@ -105,7 +105,7 @@ class SettingsPage extends React.Component {
name="download_directory" name="download_directory"
defaultValue={daemonSettings.download_directory} defaultValue={daemonSettings.download_directory}
helper="LBRY downloads will be saved here." helper="LBRY downloads will be saved here."
onChange={this.onDownloadDirChange} /> onChange={this.onDownloadDirChange.bind(this)} />
</div> </div>
</section> </section>
<section className="card"> <section className="card">
@ -132,7 +132,7 @@ class SettingsPage extends React.Component {
defaultValue={daemonSettings.max_upload} defaultValue={daemonSettings.max_upload}
placeholder="10" placeholder="10"
className="form-field__input--inline" className="form-field__input--inline"
onChange={this.onMaxUploadFieldChange} onChange={this.onMaxUploadFieldChange.bind(this)}
/> />
: '' : ''
@ -160,7 +160,7 @@ class SettingsPage extends React.Component {
defaultValue={daemonSettings.max_download} defaultValue={daemonSettings.max_download}
placeholder="10" placeholder="10"
className="form-field__input--inline" className="form-field__input--inline"
onChange={this.onMaxDownloadFieldChange} onChange={this.onMaxDownloadFieldChange.bind(this)}
/> />
: '' : ''
@ -175,13 +175,13 @@ class SettingsPage extends React.Component {
</div> </div>
<div className="card__content"> <div className="card__content">
<FormRow type="checkbox" <FormRow type="checkbox"
onChange={this.onShowUnavailableChange} onChange={this.onShowUnavailableChange.bind(this)}
defaultChecked={this.state.showUnavailable} defaultChecked={this.state.showUnavailable}
label="Show unavailable content in search results" /> label="Show unavailable content in search results" />
</div> </div>
<div className="card__content"> <div className="card__content">
<FormRow label="Show NSFW content" type="checkbox" <FormRow label="Show NSFW content" type="checkbox"
onChange={this.onShowNsfwChange} defaultChecked={this.state.showNsfw} onChange={this.onShowNsfwChange.bind(this)} defaultChecked={this.state.showNsfw}
helper="NSFW content may include nudity, intense sexuality, profanity, or other adult content. By displaying NSFW content, you are affirming you are of legal age to view mature content in your country or jurisdiction. " /> helper="NSFW content may include nudity, intense sexuality, profanity, or other adult content. By displaying NSFW content, you are affirming you are of legal age to view mature content in your country or jurisdiction. " />
</div> </div>
</section> </section>
@ -191,7 +191,7 @@ class SettingsPage extends React.Component {
</div> </div>
<div className="card__content"> <div className="card__content">
<FormRow type="checkbox" <FormRow type="checkbox"
onChange={this.onShareDataChange} onChange={this.onShareDataChange.bind(this)}
defaultChecked={daemonSettings.share_usage_data} defaultChecked={daemonSettings.share_usage_data}
label="Help make LBRY better by contributing diagnostic data about my usage" /> label="Help make LBRY better by contributing diagnostic data about my usage" />
</div> </div>

View file

@ -49,7 +49,7 @@ class ShowPage extends React.Component{
</section> </section>
} }
else if (claim.name.length && claim.name[0] === '@') { else if (claim.name.length && claim.name[0] === '@') {
innerContent = <ChannelPage uri={lbryuri.build({ name: claim.name, claimId: claim.claim_id })} /> innerContent = <ChannelPage uri={uri} />
} }
else if (claim) { else if (claim) {
innerContent = <FilePage uri={uri} /> innerContent = <FilePage uri={uri} />

View file

@ -57,6 +57,22 @@ reducers[types.CLAIM_LIST_MINE_COMPLETED] = function(state, action) {
}) })
} }
// reducers[types.FETCH_CHANNEL_CLAIMS_STARTED] = function(state, action) {
// const {
// uri,
// } = action.data
//
// const newClaims = Object.assign({}, state.claimsByChannel)
//
// if (claims !== undefined) {
// newClaims[uri] = claims
// }
//
// return Object.assign({}, state, {
// claimsByChannel: newClaims
// })
// }
reducers[types.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) { reducers[types.FETCH_CHANNEL_CLAIMS_COMPLETED] = function(state, action) {
const { const {
uri, uri,